From 3b220c587207ebfe48e7bcc3634b403756877e90 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 17 Sep 2024 21:38:31 +0000 Subject: [PATCH 001/170] feat(RingTheory/StandardSmooth): ring isomorphisms are standard smooth (#16869) We show that any `R`-algebra `S` where `algebraMap R S` is bijective, is standard smooth by constructing an explicit submersive presentation. This contribution was created as part of the AIM workshop "Formalizing algebraic geometry" in June 2024. --- Mathlib/Algebra/MvPolynomial/Equiv.lean | 11 ++++ Mathlib/RingTheory/AlgebraicIndependent.lean | 6 +- Mathlib/RingTheory/Generators.lean | 12 ++++ Mathlib/RingTheory/Presentation.lean | 33 ++++++++++ Mathlib/RingTheory/Smooth/StandardSmooth.lean | 64 ++++++++++++++++++- 5 files changed, 120 insertions(+), 6 deletions(-) diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index a6350e2e62a69..7b6e4a464b071 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -196,6 +196,17 @@ def isEmptyAlgEquiv [he : IsEmpty σ] : MvPolynomial σ R ≃ₐ[R] R := ext i m exact IsEmpty.elim' he i) +variable {R S₁ σ} in +@[simp] +lemma aeval_injective_iff_of_isEmpty [IsEmpty σ] [CommSemiring S₁] [Algebra R S₁] {f : σ → S₁} : + Function.Injective (aeval f : MvPolynomial σ R →ₐ[R] S₁) ↔ + Function.Injective (algebraMap R S₁) := by + have : aeval f = (Algebra.ofId R S₁).comp (@isEmptyAlgEquiv R σ _ _).toAlgHom := by + ext i + exact IsEmpty.elim' ‹IsEmpty σ› i + rw [this, ← Injective.of_comp_iff' _ (@isEmptyAlgEquiv R σ _ _).bijective] + rfl + /-- The ring isomorphism between multivariable polynomials in no variables and the ground ring. -/ @[simps!] diff --git a/Mathlib/RingTheory/AlgebraicIndependent.lean b/Mathlib/RingTheory/AlgebraicIndependent.lean index b0e1db85e19c4..0e358adaa9418 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent.lean @@ -82,11 +82,7 @@ theorem algebraicIndependent_iff_injective_aeval : @[simp] theorem algebraicIndependent_empty_type_iff [IsEmpty ι] : AlgebraicIndependent R x ↔ Injective (algebraMap R A) := by - have : aeval x = (Algebra.ofId R A).comp (@isEmptyAlgEquiv R ι _ _).toAlgHom := by - ext i - exact IsEmpty.elim' ‹IsEmpty ι› i - rw [AlgebraicIndependent, this, ← Injective.of_comp_iff' _ (@isEmptyAlgEquiv R ι _ _).bijective] - rfl + rw [algebraicIndependent_iff_injective_aeval, MvPolynomial.aeval_injective_iff_of_isEmpty] namespace AlgebraicIndependent diff --git a/Mathlib/RingTheory/Generators.lean b/Mathlib/RingTheory/Generators.lean index 8cd1cdb774bff..3ded91b21c690 100644 --- a/Mathlib/RingTheory/Generators.lean +++ b/Mathlib/RingTheory/Generators.lean @@ -106,6 +106,18 @@ def ofSurjective {vars} (val : vars → S) (h : Function.Surjective (aeval (R := σ' x := (h x).choose aeval_val_σ' x := (h x).choose_spec +/-- If `algebraMap R S` is surjective, the empty type generates `S`. -/ +noncomputable def ofSurjectiveAlgebraMap (h : Function.Surjective (algebraMap R S)) : + Generators.{w} R S := + ofSurjective PEmpty.elim <| fun s ↦ by + use C (h s).choose + simp [(h s).choose_spec] + +/-- The canonical generators for `R` as an `R`-algebra. -/ +noncomputable def id : Generators.{w} R R := ofSurjectiveAlgebraMap <| by + rw [id.map_eq_id] + exact RingHomSurjective.is_surjective + /-- Construct `Generators` from an assignment `I → S` such that `R[X] → S` is surjective. -/ noncomputable def ofAlgHom {I} (f : MvPolynomial I R →ₐ[R] S) (h : Function.Surjective f) : diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index b7d31cd531382..6de568a38eb2b 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -123,6 +123,39 @@ lemma finitePresentation_of_isFinite [P.IsFinite] : section Construction +/-- If `algebraMap R S` is bijective, the empty generators are a presentation with no relations. -/ +noncomputable def ofBijectiveAlgebraMap (h : Function.Bijective (algebraMap R S)) : + Presentation.{t, w} R S where + __ := Generators.ofSurjectiveAlgebraMap h.surjective + rels := PEmpty + relation := PEmpty.elim + span_range_relation_eq_ker := by + simp only [Set.range_eq_empty, Ideal.span_empty] + symm + rw [← RingHom.injective_iff_ker_eq_bot] + show Function.Injective (aeval PEmpty.elim) + rw [aeval_injective_iff_of_isEmpty] + exact h.injective + +instance ofBijectiveAlgebraMap_isFinite (h : Function.Bijective (algebraMap R S)) : + (ofBijectiveAlgebraMap.{t, w} h).IsFinite where + finite_vars := inferInstanceAs (Finite PEmpty.{w + 1}) + finite_rels := inferInstanceAs (Finite PEmpty.{t + 1}) + +lemma ofBijectiveAlgebraMap_dimension (h : Function.Bijective (algebraMap R S)) : + (ofBijectiveAlgebraMap h).dimension = 0 := by + show Nat.card PEmpty - Nat.card PEmpty = 0 + simp only [Nat.card_eq_fintype_card, Fintype.card_ofIsEmpty, le_refl, tsub_eq_zero_of_le] + +variable (R) in +/-- The canonical `R`-presentation of `R` with no generators and no relations. -/ +noncomputable def id : Presentation.{t, w} R R := ofBijectiveAlgebraMap Function.bijective_id + +instance : (id R).IsFinite := ofBijectiveAlgebraMap_isFinite (R := R) Function.bijective_id + +lemma id_dimension : (Presentation.id R).dimension = 0 := + ofBijectiveAlgebraMap_dimension (R := R) Function.bijective_id + section Localization variable (r : R) [IsLocalization.Away r S] diff --git a/Mathlib/RingTheory/Smooth/StandardSmooth.lean b/Mathlib/RingTheory/Smooth/StandardSmooth.lean index 33b0d6650afea..67da17a5eccf5 100644 --- a/Mathlib/RingTheory/Smooth/StandardSmooth.lean +++ b/Mathlib/RingTheory/Smooth/StandardSmooth.lean @@ -89,7 +89,7 @@ in June 2024. universe t t' w w' u v -open TensorProduct +open TensorProduct Classical variable (n : ℕ) @@ -167,6 +167,33 @@ lemma jacobiMatrix_apply (i j : P.rels) : end Matrix +section Constructions + +/-- If `algebraMap R S` is bijective, the empty generators are a pre-submersive +presentation with no relations. -/ +noncomputable def ofBijectiveAlgebraMap (h : Function.Bijective (algebraMap R S)) : + PreSubmersivePresentation.{t, w} R S where + toPresentation := Presentation.ofBijectiveAlgebraMap.{t, w} h + map := PEmpty.elim + map_inj (a b : PEmpty) h := by contradiction + relations_finite := inferInstanceAs (Finite PEmpty.{t + 1}) + +instance (h : Function.Bijective (algebraMap R S)) : Fintype (ofBijectiveAlgebraMap h).vars := + inferInstanceAs (Fintype PEmpty) + +instance (h : Function.Bijective (algebraMap R S)) : Fintype (ofBijectiveAlgebraMap h).rels := + inferInstanceAs (Fintype PEmpty) + +lemma ofBijectiveAlgebraMap_jacobian (h : Function.Bijective (algebraMap R S)) : + (ofBijectiveAlgebraMap h).jacobian = 1 := by + have : (algebraMap (ofBijectiveAlgebraMap h).Ring S).mapMatrix + (ofBijectiveAlgebraMap h).jacobiMatrix = 1 := by + ext (i j : PEmpty) + contradiction + rw [jacobian_eq_jacobiMatrix_det, RingHom.map_det, this, Matrix.det_one] + +end Constructions + end PreSubmersivePresentation /-- @@ -180,6 +207,31 @@ structure SubmersivePresentation extends PreSubmersivePresentation.{t, w} R S wh attribute [instance] SubmersivePresentation.isFinite +namespace SubmersivePresentation + +open PreSubmersivePresentation + +section Constructions + +variable {R S} in +/-- If `algebraMap R S` is bijective, the empty generators are a submersive +presentation with no relations. -/ +noncomputable def ofBijectiveAlgebraMap (h : Function.Bijective (algebraMap R S)) : + SubmersivePresentation.{t, w} R S where + __ := PreSubmersivePresentation.ofBijectiveAlgebraMap.{t, w} h + jacobian_isUnit := by + rw [ofBijectiveAlgebraMap_jacobian] + exact isUnit_one + isFinite := Presentation.ofBijectiveAlgebraMap_isFinite h + +/-- The canonical submersive `R`-presentation of `R` with no generators and no relations. -/ +noncomputable def id : SubmersivePresentation.{t, w} R R := + ofBijectiveAlgebraMap Function.bijective_id + +end Constructions + +end SubmersivePresentation + /-- An `R`-algebra `S` is called standard smooth, if there exists a submersive presentation. @@ -211,6 +263,16 @@ lemma IsStandardSmoothOfRelativeDimension.isStandardSmooth IsStandardSmooth.{t, w} R S := ⟨‹IsStandardSmoothOfRelativeDimension n R S›.out.nonempty⟩ +lemma IsStandardSmoothOfRelativeDimension.of_algebraMap_bijective + (h : Function.Bijective (algebraMap R S)) : + IsStandardSmoothOfRelativeDimension.{t, w} 0 R S := + ⟨SubmersivePresentation.ofBijectiveAlgebraMap h, Presentation.ofBijectiveAlgebraMap_dimension h⟩ + +variable (R) in +instance IsStandardSmoothOfRelativeDimension.id : + IsStandardSmoothOfRelativeDimension.{t, w} 0 R R := + IsStandardSmoothOfRelativeDimension.of_algebraMap_bijective Function.bijective_id + end Algebra namespace RingHom From 19286096b043cde919aab517b44227815226e7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 17 Sep 2024 23:02:48 +0000 Subject: [PATCH 002/170] chore(SetTheory/Cardinal/Basic): inline `mul_comm` into instance (#16851) We also make the arguments of `power_zero`, `power_one`, and `power_add` explicit. --- Mathlib/SetTheory/Cardinal/Basic.lean | 40 ++++++++++++--------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index d897e2051a169..729fd4ba6c61f 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -405,11 +405,6 @@ theorem mk_psum (α : Type u) (β : Type v) : #(α ⊕' β) = lift.{v} #α + lif theorem mk_fintype (α : Type u) [h : Fintype α] : #α = Fintype.card α := mk_congr (Fintype.equivOfCardEq (by simp)) -protected theorem cast_succ (n : ℕ) : ((n + 1 : ℕ) : Cardinal.{u}) = n + 1 := by - change #(ULift.{u} (Fin (n+1))) = # (ULift.{u} (Fin n)) + 1 - rw [← mk_option, mk_fintype, mk_fintype] - simp only [Fintype.card_ulift, Fintype.card_fin, Fintype.card_option] - instance : Mul Cardinal.{u} := ⟨map₂ Prod fun _ _ _ _ => Equiv.prodCongr⟩ @@ -420,9 +415,6 @@ theorem mul_def (α β : Type u) : #α * #β = #(α × β) := theorem mk_prod (α : Type u) (β : Type v) : #(α × β) = lift.{v, u} #α * lift.{u, v} #β := mk_congr (Equiv.ulift.symm.prodCongr Equiv.ulift.symm) -private theorem mul_comm' (a b : Cardinal.{u}) : a * b = b * a := - inductionOn₂ a b fun α β => mk_congr <| Equiv.prodComm α β - /-- The cardinal exponential. `#α ^ #β` is the cardinal of `β → α`. -/ instance instPowCardinal : Pow Cardinal.{u} Cardinal.{u} := ⟨map₂ (fun α β => β → α) fun _ _ _ _ e₁ e₂ => e₂.arrowCongr e₁⟩ @@ -439,41 +431,45 @@ theorem lift_power (a b : Cardinal.{u}) : lift.{v} (a ^ b) = lift.{v} a ^ lift.{ mk_congr <| Equiv.ulift.trans (Equiv.ulift.arrowCongr Equiv.ulift).symm @[simp] -theorem power_zero {a : Cardinal} : a ^ (0 : Cardinal) = 1 := +theorem power_zero (a : Cardinal) : a ^ (0 : Cardinal) = 1 := inductionOn a fun _ => mk_eq_one _ @[simp] -theorem power_one {a : Cardinal.{u}} : a ^ (1 : Cardinal) = a := +theorem power_one (a : Cardinal.{u}) : a ^ (1 : Cardinal) = a := inductionOn a fun α => mk_congr (Equiv.funUnique (ULift.{u} (Fin 1)) α) -theorem power_add {a b c : Cardinal} : a ^ (b + c) = a ^ b * a ^ c := +theorem power_add (a b c : Cardinal) : a ^ (b + c) = a ^ b * a ^ c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.sumArrowEquivProdArrow β γ α +private theorem cast_succ (n : ℕ) : ((n + 1 : ℕ) : Cardinal.{u}) = n + 1 := by + change #(ULift.{u} _) = #(ULift.{u} _) + 1 + rw [← mk_option] + simp + instance commSemiring : CommSemiring Cardinal.{u} where zero := 0 one := 1 add := (· + ·) mul := (· * ·) - zero_add a := inductionOn a fun α => mk_congr <| Equiv.emptySum (ULift (Fin 0)) α - add_zero a := inductionOn a fun α => mk_congr <| Equiv.sumEmpty α (ULift (Fin 0)) + zero_add a := inductionOn a fun α => mk_congr <| Equiv.emptySum _ α + add_zero a := inductionOn a fun α => mk_congr <| Equiv.sumEmpty α _ add_assoc a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.sumAssoc α β γ add_comm a b := inductionOn₂ a b fun α β => mk_congr <| Equiv.sumComm α β zero_mul a := inductionOn a fun α => mk_eq_zero _ mul_zero a := inductionOn a fun α => mk_eq_zero _ - one_mul a := inductionOn a fun α => mk_congr <| Equiv.uniqueProd α (ULift (Fin 1)) - mul_one a := inductionOn a fun α => mk_congr <| Equiv.prodUnique α (ULift (Fin 1)) + one_mul a := inductionOn a fun α => mk_congr <| Equiv.uniqueProd α _ + mul_one a := inductionOn a fun α => mk_congr <| Equiv.prodUnique α _ mul_assoc a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.prodAssoc α β γ - mul_comm := mul_comm' + mul_comm a b := inductionOn₂ a b fun α β => mk_congr <| Equiv.prodComm α β left_distrib a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.prodSumDistrib α β γ right_distrib a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.sumProdDistrib α β γ nsmul := nsmulRec npow n c := c ^ (n : Cardinal) - npow_zero := @power_zero - npow_succ n c := show c ^ (↑(n + 1) : Cardinal) = c ^ (↑n : Cardinal) * c - by rw [Cardinal.cast_succ, power_add, power_one, mul_comm'] - natCast := (fun n => lift.{u} #(Fin n) : ℕ → Cardinal.{u}) + npow_zero := power_zero + npow_succ n c := by dsimp; rw [cast_succ, power_add, power_one] + natCast n := lift #(Fin n) natCast_zero := rfl - natCast_succ := Cardinal.cast_succ + natCast_succ n := cast_succ n @[simp] theorem one_power {a : Cardinal} : (1 : Cardinal) ^ a = 1 := @@ -614,7 +610,7 @@ theorem self_le_power (a : Cardinal) {b : Cardinal} (hb : 1 ≤ b) : a ≤ a ^ b rcases eq_or_ne a 0 with (rfl | ha) · exact zero_le _ · convert power_le_power_left ha hb - exact power_one.symm + exact (power_one a).symm /-- **Cantor's theorem** -/ theorem cantor (a : Cardinal.{u}) : a < 2 ^ a := by From fb04c4bf0455500a8e936d90da9e89e4840f94cf Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Tue, 17 Sep 2024 23:58:31 +0000 Subject: [PATCH 003/170] feat(Normed/Field): `completeSpace_iff_isComplete_closedBall` (#15777) On the way to locally complete K iff complete O(K) Also add some helper lemmas about uniform continuity of multiplication by a constant with a variant for rings (via smul) instead of UniformGroup (which fields are not). Co-authored-by: Yakov Pechersky Co-authored-by: Yakov Pechersky --- Mathlib/Analysis/Normed/Field/Basic.lean | 43 ++++++++++++++ Mathlib/Analysis/Normed/Field/Lemmas.lean | 59 +++++++++++++++++++ Mathlib/Analysis/Normed/Group/Uniform.lean | 13 ++++ Mathlib/Topology/Algebra/UniformGroup.lean | 27 +++++++++ .../Topology/Algebra/UniformMulAction.lean | 33 +++++++++++ 5 files changed, 175 insertions(+) diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index 02d24cb406d37..56b1e27ee82ae 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -14,6 +14,9 @@ import Mathlib.Data.Set.Pointwise.Interval In this file we define (semi)normed rings and fields. We also prove some theorems about these definitions. + +Some useful results that relate the topology of the normed field to the discrete topology include: +* `norm_eq_one_iff_ne_zero_of_discrete` -/ -- Guard against import creep. @@ -669,6 +672,46 @@ theorem nndist_inv_inv₀ {z w : α} (hz : z ≠ 0) (hw : w ≠ 0) : nndist z⁻¹ w⁻¹ = nndist z w / (‖z‖₊ * ‖w‖₊) := NNReal.eq <| dist_inv_inv₀ hz hw +namespace NormedDivisionRing + +section Discrete + +variable {𝕜 : Type*} [NormedDivisionRing 𝕜] [DiscreteTopology 𝕜] + +lemma norm_eq_one_iff_ne_zero_of_discrete {x : 𝕜} : ‖x‖ = 1 ↔ x ≠ 0 := by + constructor <;> intro hx + · contrapose! hx + simp [hx] + · have : IsOpen {(0 : 𝕜)} := isOpen_discrete {0} + simp_rw [Metric.isOpen_singleton_iff, dist_eq_norm, sub_zero] at this + obtain ⟨ε, εpos, h'⟩ := this + wlog h : ‖x‖ < 1 generalizing 𝕜 with H + · push_neg at h + rcases h.eq_or_lt with h|h + · rw [h] + replace h := norm_inv x ▸ inv_lt_one h + rw [← inv_inj, inv_one, ← norm_inv] + exact H (by simpa) h' h + obtain ⟨k, hk⟩ : ∃ k : ℕ, ‖x‖ ^ k < ε := exists_pow_lt_of_lt_one εpos h + rw [← norm_pow] at hk + specialize h' _ hk + simp [hx] at h' + +@[simp] +lemma norm_le_one_of_discrete + (x : 𝕜) : ‖x‖ ≤ 1 := by + rcases eq_or_ne x 0 with rfl|hx + · simp + · simp [norm_eq_one_iff_ne_zero_of_discrete.mpr hx] + +lemma discreteTopology_unit_closedBall_eq_univ : (Metric.closedBall 0 1 : Set 𝕜) = Set.univ := by + ext + simp + +end Discrete + +end NormedDivisionRing + end NormedDivisionRing /-- A normed field is a field with a norm satisfying ‖x y‖ = ‖x‖ ‖y‖. -/ diff --git a/Mathlib/Analysis/Normed/Field/Lemmas.lean b/Mathlib/Analysis/Normed/Field/Lemmas.lean index f56d61465db91..7b97a37837eb7 100644 --- a/Mathlib/Analysis/Normed/Field/Lemmas.lean +++ b/Mathlib/Analysis/Normed/Field/Lemmas.lean @@ -17,6 +17,11 @@ import Mathlib.Topology.MetricSpace.DilationEquiv # Normed fields In this file we continue building the theory of (semi)normed rings and fields. + +Some useful results that relate the topology of the normed field to the discrete topology include: +* `discreteTopology_or_nontriviallyNormedField` +* `discreteTopology_of_bddAbove_range_norm` + -/ -- Guard against import creep. @@ -291,6 +296,32 @@ end NormedDivisionRing namespace NormedField +/-- A normed field is either nontrivially normed or has a discrete topology. +In the discrete topology case, all the norms are 1, by `norm_eq_one_iff_ne_zero_of_discrete`. +The nontrivially normed field instance is provided by a subtype with a proof that the +forgetful inheritance to the existing `NormedField` instance is definitionally true. +This allows one to have the new `NontriviallyNormedField` instance without data clashes. -/ +lemma discreteTopology_or_nontriviallyNormedField (𝕜 : Type*) [h : NormedField 𝕜] : + DiscreteTopology 𝕜 ∨ Nonempty ({h' : NontriviallyNormedField 𝕜 // h'.toNormedField = h}) := by + by_cases H : ∃ x : 𝕜, x ≠ 0 ∧ ‖x‖ ≠ 1 + · exact Or.inr ⟨(⟨NontriviallyNormedField.ofNormNeOne H, rfl⟩)⟩ + · simp_rw [discreteTopology_iff_isOpen_singleton_zero, Metric.isOpen_singleton_iff, dist_eq_norm, + sub_zero] + refine Or.inl ⟨1, zero_lt_one, ?_⟩ + contrapose! H + refine H.imp ?_ + -- contextual to reuse the `a ≠ 0` hypothesis in the proof of `a ≠ 0 ∧ ‖a‖ ≠ 1` + simp (config := {contextual := true}) [add_comm, ne_of_lt] + +lemma discreteTopology_of_bddAbove_range_norm {𝕜 : Type*} [NormedField 𝕜] + (h : BddAbove (Set.range fun k : 𝕜 ↦ ‖k‖)) : + DiscreteTopology 𝕜 := by + refine (NormedField.discreteTopology_or_nontriviallyNormedField _).resolve_right ?_ + rintro ⟨_, rfl⟩ + obtain ⟨x, h⟩ := h + obtain ⟨k, hk⟩ := NormedField.exists_lt_norm 𝕜 x + exact hk.not_le (h (Set.mem_range_self k)) + section Densely variable (α) [DenselyNormedField α] @@ -333,3 +364,31 @@ instance Rat.instDenselyNormedField : DenselyNormedField ℚ where lt_norm_lt r₁ r₂ h₀ hr := let ⟨q, h⟩ := exists_rat_btwn hr ⟨q, by rwa [← Rat.norm_cast_real, Real.norm_eq_abs, abs_of_pos (h₀.trans_lt h.1)]⟩ + +section Complete + +lemma NormedField.completeSpace_iff_isComplete_closedBall {K : Type*} [NormedField K] : + CompleteSpace K ↔ IsComplete (Metric.closedBall 0 1 : Set K) := by + constructor <;> intro h + · exact Metric.isClosed_ball.isComplete + rcases NormedField.discreteTopology_or_nontriviallyNormedField K with _|⟨_, rfl⟩ + · rwa [completeSpace_iff_isComplete_univ, + ← NormedDivisionRing.discreteTopology_unit_closedBall_eq_univ] + refine Metric.complete_of_cauchySeq_tendsto fun u hu ↦ ?_ + obtain ⟨k, hk⟩ := hu.norm_bddAbove + have kpos : 0 ≤ k := (_root_.norm_nonneg (u 0)).trans (hk (by simp)) + obtain ⟨x, hx⟩ := NormedField.exists_lt_norm K k + have hu' : CauchySeq ((· / x) ∘ u) := (uniformContinuous_div_const' x).comp_cauchySeq hu + have hb : ∀ n, ((· / x) ∘ u) n ∈ Metric.closedBall 0 1 := by + intro + simp only [Function.comp_apply, Metric.mem_closedBall, dist_zero_right, norm_div] + rw [div_le_one (kpos.trans_lt hx)] + exact hx.le.trans' (hk (by simp)) + obtain ⟨a, -, ha'⟩ := cauchySeq_tendsto_of_isComplete h hb hu' + refine ⟨a * x, (((continuous_mul_right x).tendsto a).comp ha').congr ?_⟩ + have hx' : x ≠ 0 := by + contrapose! hx + simp [hx, kpos] + simp [div_mul_cancel₀ _ hx'] + +end Complete diff --git a/Mathlib/Analysis/Normed/Group/Uniform.lean b/Mathlib/Analysis/Normed/Group/Uniform.lean index 42621d3976ca7..7ec9757016b86 100644 --- a/Mathlib/Analysis/Normed/Group/Uniform.lean +++ b/Mathlib/Analysis/Normed/Group/Uniform.lean @@ -379,4 +379,17 @@ theorem cauchySeq_prod_of_eventually_eq {u v : ℕ → E} {N : ℕ} (huv : ∀ n intro m hm simp [huv m (le_of_lt hm)] +@[to_additive CauchySeq.norm_bddAbove] +lemma CauchySeq.mul_norm_bddAbove {G : Type*} [SeminormedGroup G] {u : ℕ → G} + (hu : CauchySeq u) : BddAbove (Set.range (fun n ↦ ‖u n‖)) := by + obtain ⟨C, -, hC⟩ := cauchySeq_bdd hu + simp_rw [SeminormedGroup.dist_eq] at hC + have : ∀ n, ‖u n‖ ≤ C + ‖u 0‖ := by + intro n + rw [add_comm] + refine (norm_le_norm_add_norm_div' (u n) (u 0)).trans ?_ + simp [(hC _ _).le] + rw [bddAbove_def] + exact ⟨C + ‖u 0‖, by simpa using this⟩ + end SeminormedCommGroup diff --git a/Mathlib/Topology/Algebra/UniformGroup.lean b/Mathlib/Topology/Algebra/UniformGroup.lean index b160ebca22eed..f6f8cdc90796d 100644 --- a/Mathlib/Topology/Algebra/UniformGroup.lean +++ b/Mathlib/Topology/Algebra/UniformGroup.lean @@ -93,6 +93,33 @@ theorem UniformContinuous.mul [UniformSpace β] {f : β → α} {g : β → α} theorem uniformContinuous_mul : UniformContinuous fun p : α × α => p.1 * p.2 := uniformContinuous_fst.mul uniformContinuous_snd +@[to_additive] +theorem UniformContinuous.mul_const [UniformSpace β] {f : β → α} (hf : UniformContinuous f) + (a : α) : UniformContinuous fun x ↦ f x * a := + hf.mul uniformContinuous_const + +@[to_additive] +theorem UniformContinuous.const_mul [UniformSpace β] {f : β → α} (hf : UniformContinuous f) + (a : α) : UniformContinuous fun x ↦ a * f x := + uniformContinuous_const.mul hf + +@[to_additive] +theorem uniformContinuous_mul_left (a : α) : UniformContinuous fun b : α => a * b := + uniformContinuous_id.const_mul _ + +@[to_additive] +theorem uniformContinuous_mul_right (a : α) : UniformContinuous fun b : α => b * a := + uniformContinuous_id.mul_const _ + +@[to_additive] +theorem UniformContinuous.div_const [UniformSpace β] {f : β → α} (hf : UniformContinuous f) + (a : α) : UniformContinuous fun x ↦ f x / a := + hf.div uniformContinuous_const + +@[to_additive] +theorem uniformContinuous_div_const (a : α) : UniformContinuous fun b : α => b / a := + uniformContinuous_id.div_const _ + @[to_additive UniformContinuous.const_nsmul] theorem UniformContinuous.pow_const [UniformSpace β] {f : β → α} (hf : UniformContinuous f) : ∀ n : ℕ, UniformContinuous fun x => f x ^ n diff --git a/Mathlib/Topology/Algebra/UniformMulAction.lean b/Mathlib/Topology/Algebra/UniformMulAction.lean index 4c23eda8c9359..d98b4c082accb 100644 --- a/Mathlib/Topology/Algebra/UniformMulAction.lean +++ b/Mathlib/Topology/Algebra/UniformMulAction.lean @@ -116,6 +116,39 @@ instance UniformGroup.to_uniformContinuousConstSMul {G : Type u} [Group G] [Unif [UniformGroup G] : UniformContinuousConstSMul G G := ⟨fun _ => uniformContinuous_const.mul uniformContinuous_id⟩ +section Ring + +variable {R β : Type*} [Ring R] [UniformSpace R] [UniformSpace β] + +theorem UniformContinuous.const_mul' [UniformContinuousConstSMul R R] {f : β → R} + (hf : UniformContinuous f) (a : R) : UniformContinuous fun x ↦ a * f x := + hf.const_smul a + +theorem UniformContinuous.mul_const' [UniformContinuousConstSMul Rᵐᵒᵖ R] {f : β → R} + (hf : UniformContinuous f) (a : R) : UniformContinuous fun x ↦ f x * a := + hf.const_smul (MulOpposite.op a) + +theorem uniformContinuous_mul_left' [UniformContinuousConstSMul R R] (a : R) : + UniformContinuous fun b : R => a * b := + uniformContinuous_id.const_mul' _ + +theorem uniformContinuous_mul_right' [UniformContinuousConstSMul Rᵐᵒᵖ R] (a : R) : + UniformContinuous fun b : R => b * a := + uniformContinuous_id.mul_const' _ + +theorem UniformContinuous.div_const' {R β : Type*} [DivisionRing R] [UniformSpace R] + [UniformContinuousConstSMul Rᵐᵒᵖ R] [UniformSpace β] {f : β → R} + (hf : UniformContinuous f) (a : R) : + UniformContinuous fun x ↦ f x / a := by + simpa [div_eq_mul_inv] using hf.mul_const' a⁻¹ + +theorem uniformContinuous_div_const' {R : Type*} [DivisionRing R] [UniformSpace R] + [UniformContinuousConstSMul Rᵐᵒᵖ R] (a : R) : + UniformContinuous fun b : R => b / a := + uniformContinuous_id.div_const' _ + +end Ring + namespace UniformSpace namespace Completion From f1027bcd7993d1f7dee629b1453a47537940b8dd Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 18 Sep 2024 01:02:31 +0000 Subject: [PATCH 004/170] feat(Filter/Ker): prove `ker_iSup` etc (#16632) --- Mathlib/Order/Filter/Ker.lean | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Mathlib/Order/Filter/Ker.lean b/Mathlib/Order/Filter/Ker.lean index 64eecf4a76499..29f0a9d1d3129 100644 --- a/Mathlib/Order/Filter/Ker.lean +++ b/Mathlib/Order/Filter/Ker.lean @@ -54,4 +54,21 @@ lemma ker_surjective : Surjective (ker : Filter α → Set α) := gi_principal_k simp only [mem_ker, mem_comap, forall_exists_index, and_imp, @forall_swap (Set α), mem_preimage] exact forall₂_congr fun s _ ↦ ⟨fun h ↦ h _ Subset.rfl, fun ha t ht ↦ ht ha⟩ +@[simp] +theorem ker_iSup (f : ι → Filter α) : ker (⨆ i, f i) = ⋃ i, ker (f i) := by + refine subset_antisymm (fun x hx ↦ ?_) ker_mono.le_map_iSup + simp only [mem_iUnion, mem_ker] at hx ⊢ + contrapose! hx + choose s hsf hxs using hx + refine ⟨⋃ i, s i, ?_, by simpa⟩ + exact mem_iSup.2 fun i ↦ mem_of_superset (hsf i) (subset_iUnion s i) + +@[simp] +theorem ker_sSup (S : Set (Filter α)) : ker (sSup S) = ⋃ f ∈ S, ker f := by + simp [sSup_eq_iSup] + +@[simp] +theorem ker_sup (f g : Filter α) : ker (f ⊔ g) = ker f ∪ ker g := by + rw [← sSup_pair, ker_sSup, biUnion_pair] + end Filter From d7e322a1042181dac5c9021a046f24105cc3d497 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 18 Sep 2024 01:17:38 +0000 Subject: [PATCH 005/170] =?UTF-8?q?feat(List/Enum):=20add=20lemmas=20about?= =?UTF-8?q?=20`=E2=88=80=20x=20=E2=88=88=20l.enum,=20p=20x`=20etc=20(#1678?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Data/List/Enum.lean | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Mathlib/Data/List/Enum.lean b/Mathlib/Data/List/Enum.lean index edc801c308976..d4b73fc6bec78 100644 --- a/Mathlib/Data/List/Enum.lean +++ b/Mathlib/Data/List/Enum.lean @@ -3,18 +3,17 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Yakov Pechersky, Eric Wieser -/ -import Batteries.Tactic.Alias -import Mathlib.Tactic.TypeStar -import Mathlib.Data.Nat.Notation +import Mathlib.Data.List.Basic /-! # Properties of `List.enum` ## Deprecation note -Everything in this file has been replaced by theorems in Lean4, + +Many lemmas in this file have been replaced by theorems in Lean4, in terms of `xs[i]?` and `xs[i]` rather than `get` and `get?`. -The results here are unused in Mathlib, and deprecated. +The deprecated results here are unused in Mathlib. Any downstream users who can not easily adapt may remove the deprecations as needed. -/ @@ -64,4 +63,20 @@ set_option linter.deprecated false in theorem mem_enum_iff_get? {x : ℕ × α} {l : List α} : x ∈ enum l ↔ l.get? x.1 = x.2 := mk_mem_enum_iff_get? +theorem forall_mem_enumFrom {l : List α} {n : ℕ} {p : ℕ × α → Prop} : + (∀ x ∈ l.enumFrom n, p x) ↔ ∀ (i : ℕ) (_ : i < length l), p (n + i, l[i]) := by + simp only [forall_mem_iff_getElem, getElem_enumFrom, enumFrom_length] + +theorem forall_mem_enum {l : List α} {p : ℕ × α → Prop} : + (∀ x ∈ l.enum, p x) ↔ ∀ (i : ℕ) (_ : i < length l), p (i, l[i]) := + forall_mem_enumFrom.trans <| by simp + +theorem exists_mem_enumFrom {l : List α} {n : ℕ} {p : ℕ × α → Prop} : + (∃ x ∈ l.enumFrom n, p x) ↔ ∃ (i : ℕ) (_ : i < length l), p (n + i, l[i]) := by + simp only [exists_mem_iff_getElem, getElem_enumFrom, enumFrom_length] + +theorem exists_mem_enum {l : List α} {p : ℕ × α → Prop} : + (∃ x ∈ l.enum, p x) ↔ ∃ (i : ℕ) (_ : i < length l), p (i, l[i]) := + exists_mem_enumFrom.trans <| by simp + end List From 6a73625d76f5d9e7e686f9220c26fe7836278103 Mon Sep 17 00:00:00 2001 From: Yuma Mizuno Date: Wed, 18 Sep 2024 01:47:00 +0000 Subject: [PATCH 006/170] feat(CategoryTheory): proof producing coherence tactic (#16852) See [Zulip](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Proof.20producing.20coherence.20tactic.20for.20monoidal.20categories). --- Mathlib.lean | 13 +- .../CategoryTheory/Bicategory/Adjunction.lean | 62 +- .../Bicategory/Kan/Adjunction.lean | 87 +- Mathlib/CategoryTheory/Monoidal/Bimod.lean | 24 +- .../Monoidal/Braided/Basic.lean | 47 +- Mathlib/CategoryTheory/Monoidal/Center.lean | 22 +- .../Monoidal/CoherenceLemmas.lean | 22 +- Mathlib/CategoryTheory/Monoidal/Comon_.lean | 6 +- Mathlib/CategoryTheory/Monoidal/Hopf_.lean | 4 +- Mathlib/CategoryTheory/Monoidal/Mon_.lean | 6 +- Mathlib/CategoryTheory/Monoidal/Opposite.lean | 8 +- .../CategoryTheory/Monoidal/Rigid/Basic.lean | 114 ++- .../Monoidal/Rigid/Braided.lean | 4 +- Mathlib/Tactic.lean | 13 +- .../CategoryTheory/BicategoricalComp.lean | 51 +- .../CategoryTheory/Bicategory/Basic.lean | 55 ++ .../CategoryTheory/Bicategory/Datatypes.lean | 511 ++++++++++++ .../CategoryTheory/Bicategory/Normalize.lean | 548 ++++++++++++ .../Bicategory/PureCoherence.lean | 280 +++++++ .../CategoryTheory/BicategoryCoherence.lean | 6 +- Mathlib/Tactic/CategoryTheory/Coherence.lean | 5 +- .../CategoryTheory/Coherence/Basic.lean | 107 +++ .../CategoryTheory/Coherence/Datatypes.lean | 467 +++++++++++ .../CategoryTheory/Coherence/Normalize.lean | 586 +++++++++++++ .../Coherence/PureCoherence.lean | 197 +++++ Mathlib/Tactic/CategoryTheory/Monoidal.lean | 684 --------------- .../Tactic/CategoryTheory/Monoidal/Basic.lean | 55 ++ .../CategoryTheory/Monoidal/Datatypes.lean | 505 +++++++++++ .../CategoryTheory/Monoidal/Normalize.lean | 787 ++++++++++++++++++ .../Monoidal/PureCoherence.lean | 277 ++++++ Mathlib/Tactic/Widget/StringDiagram.lean | 154 ++-- scripts/noshake.json | 6 + test/CategoryTheory/Bicategory/Basic.lean | 21 + test/CategoryTheory/Bicategory/Normalize.lean | 54 ++ test/CategoryTheory/Monoidal.lean | 52 -- test/CategoryTheory/Monoidal/Basic.lean | 27 + test/CategoryTheory/Monoidal/Normalize.lean | 41 + test/StringDiagram.lean | 80 +- 38 files changed, 4939 insertions(+), 1049 deletions(-) create mode 100644 Mathlib/Tactic/CategoryTheory/Bicategory/Basic.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Bicategory/Normalize.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Bicategory/PureCoherence.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Coherence/Basic.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Coherence/Datatypes.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Coherence/Normalize.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Coherence/PureCoherence.lean delete mode 100644 Mathlib/Tactic/CategoryTheory/Monoidal.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Monoidal/Basic.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Monoidal/Datatypes.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Monoidal/Normalize.lean create mode 100644 Mathlib/Tactic/CategoryTheory/Monoidal/PureCoherence.lean create mode 100644 test/CategoryTheory/Bicategory/Basic.lean create mode 100644 test/CategoryTheory/Bicategory/Normalize.lean delete mode 100644 test/CategoryTheory/Monoidal.lean create mode 100644 test/CategoryTheory/Monoidal/Basic.lean create mode 100644 test/CategoryTheory/Monoidal/Normalize.lean diff --git a/Mathlib.lean b/Mathlib.lean index 0fad7e2c8e664..e2b16910f49da 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4143,10 +4143,21 @@ import Mathlib.Tactic.CancelDenoms.Core import Mathlib.Tactic.Cases import Mathlib.Tactic.CasesM import Mathlib.Tactic.CategoryTheory.BicategoricalComp +import Mathlib.Tactic.CategoryTheory.Bicategory.Basic +import Mathlib.Tactic.CategoryTheory.Bicategory.Datatypes +import Mathlib.Tactic.CategoryTheory.Bicategory.Normalize +import Mathlib.Tactic.CategoryTheory.Bicategory.PureCoherence import Mathlib.Tactic.CategoryTheory.BicategoryCoherence import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Coherence.Basic +import Mathlib.Tactic.CategoryTheory.Coherence.Datatypes +import Mathlib.Tactic.CategoryTheory.Coherence.Normalize +import Mathlib.Tactic.CategoryTheory.Coherence.PureCoherence import Mathlib.Tactic.CategoryTheory.Elementwise -import Mathlib.Tactic.CategoryTheory.Monoidal +import Mathlib.Tactic.CategoryTheory.Monoidal.Basic +import Mathlib.Tactic.CategoryTheory.Monoidal.Datatypes +import Mathlib.Tactic.CategoryTheory.Monoidal.Normalize +import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence import Mathlib.Tactic.CategoryTheory.MonoidalComp import Mathlib.Tactic.CategoryTheory.Reassoc import Mathlib.Tactic.CategoryTheory.Slice diff --git a/Mathlib/CategoryTheory/Bicategory/Adjunction.lean b/Mathlib/CategoryTheory/Bicategory/Adjunction.lean index ae25dba05c39c..1c3d1f82e0da8 100644 --- a/Mathlib/CategoryTheory/Bicategory/Adjunction.lean +++ b/Mathlib/CategoryTheory/Bicategory/Adjunction.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Yuma Mizuno. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yuma Mizuno -/ -import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Bicategory.Basic /-! # Adjunctions in bicategories @@ -19,18 +19,6 @@ identities. The 2-morphism `η` is called the unit and `ε` is called the counit * `Bicategory.mkOfAdjointifyCounit`: construct an adjoint equivalence from 2-isomorphisms `η : 𝟙 a ≅ f ≫ g` and `ε : g ≫ f ≅ 𝟙 b`, by upgrading `ε` to a counit. -## Implementation notes - -The computation of 2-morphisms in the proof is done using `calc` blocks. Typically, -the LHS and the RHS in each step of `calc` are related by simple rewriting up to associators -and unitors. So the proof for each step should be of the form `rw [...]; coherence`. In practice, -our proofs look like `rw [...]; simp [bicategoricalComp]; coherence`. The `simp` is not strictly -necessary, but it speeds up the proof and allow us to avoid increasing the `maxHeartbeats`. -The speedup is probably due to reducing the length of the expression e.g. by absorbing -identity maps or applying the pentagon relation. Such a hack may not be necessary if the -coherence tactic is improved. One possible way would be to perform such a simplification in the -preprocessing of the coherence tactic. - ## TODO * `Bicategory.mkOfAdjointifyUnit`: construct an adjoint equivalence from 2-isomorphisms @@ -58,7 +46,7 @@ a ------ ▸ a b ------ ▸ b ``` -/ -def leftZigzag (η : 𝟙 a ⟶ f ≫ g) (ε : g ≫ f ⟶ 𝟙 b) := +abbrev leftZigzag (η : 𝟙 a ⟶ f ≫ g) (ε : g ≫ f ⟶ 𝟙 b) := η ▷ f ⊗≫ f ◁ ε /-- The 2-morphism defined by the following pasting diagram: @@ -70,7 +58,7 @@ def leftZigzag (η : 𝟙 a ⟶ f ≫ g) (ε : g ≫ f ⟶ 𝟙 b) := b ------ ▸ b ``` -/ -def rightZigzag (η : 𝟙 a ⟶ f ≫ g) (ε : g ≫ f ⟶ 𝟙 b) := +abbrev rightZigzag (η : 𝟙 a ⟶ f ≫ g) (ε : g ≫ f ⟶ 𝟙 b) := g ◁ η ⊗≫ ε ▷ g theorem rightZigzag_idempotent_of_left_triangle @@ -79,13 +67,13 @@ theorem rightZigzag_idempotent_of_left_triangle dsimp only [rightZigzag] calc _ = g ◁ η ⊗≫ ((ε ▷ g ▷ 𝟙 a) ≫ (𝟙 b ≫ g) ◁ η) ⊗≫ ε ▷ g := by - simp [bicategoricalComp]; coherence + bicategory _ = 𝟙 _ ⊗≫ g ◁ (η ▷ 𝟙 a ≫ (f ≫ g) ◁ η) ⊗≫ (ε ▷ (g ≫ f) ≫ 𝟙 b ◁ ε) ▷ g ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; simp [bicategoricalComp]; coherence + rw [← whisker_exchange]; bicategory _ = g ◁ η ⊗≫ g ◁ leftZigzag η ε ▷ g ⊗≫ ε ▷ g := by - rw [← whisker_exchange, ← whisker_exchange]; simp [leftZigzag, bicategoricalComp]; coherence + rw [← whisker_exchange, ← whisker_exchange, leftZigzag]; bicategory _ = g ◁ η ⊗≫ ε ▷ g := by - rw [h]; simp [bicategoricalComp]; coherence + rw [h]; bicategory /-- Adjunction between two 1-morphisms. -/ structure Adjunction (f : a ⟶ b) (g : b ⟶ a) where @@ -104,14 +92,14 @@ namespace Adjunction attribute [simp] left_triangle right_triangle -attribute [local simp] leftZigzag rightZigzag +-- attribute [local simp] leftZigzag rightZigzag /-- Adjunction between identities. -/ def id (a : B) : 𝟙 a ⊣ 𝟙 a where unit := (ρ_ _).inv counit := (ρ_ _).hom - left_triangle := by dsimp; coherence - right_triangle := by dsimp; coherence + left_triangle := by bicategory_coherence + right_triangle := by bicategory_coherence instance : Inhabited (Adjunction (𝟙 a) (𝟙 a)) := ⟨id a⟩ @@ -137,13 +125,13 @@ theorem comp_left_triangle_aux (adj₁ : f₁ ⊣ g₁) (adj₂ : f₂ ⊣ g₂) adj₁.unit ▷ (f₁ ≫ f₂) ⊗≫ f₁ ◁ (adj₂.unit ▷ (g₁ ≫ f₁) ≫ (f₂ ≫ g₂) ◁ adj₁.counit) ▷ f₂ ⊗≫ (f₁ ≫ f₂) ◁ adj₂.counit ⊗≫ 𝟙 _ := by - simp [bicategoricalComp]; coherence + dsimp only [compUnit, compCounit]; bicategory _ = 𝟙 _ ⊗≫ (leftZigzag adj₁.unit adj₁.counit) ▷ f₂ ⊗≫ f₁ ◁ (leftZigzag adj₂.unit adj₂.counit) ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; simp [bicategoricalComp]; coherence + rw [← whisker_exchange]; bicategory _ = _ := by - simp_rw [left_triangle]; simp [bicategoricalComp] + simp_rw [left_triangle]; bicategory theorem comp_right_triangle_aux (adj₁ : f₁ ⊣ g₁) (adj₂ : f₂ ⊣ g₂) : rightZigzag (compUnit adj₁ adj₂) (compCounit adj₁ adj₂) = (ρ_ _).hom ≫ (λ_ _).inv := by @@ -152,13 +140,13 @@ theorem comp_right_triangle_aux (adj₁ : f₁ ⊣ g₁) (adj₂ : f₂ ⊣ g₂ (g₂ ≫ g₁) ◁ adj₁.unit ⊗≫ g₂ ◁ ((g₁ ≫ f₁) ◁ adj₂.unit ≫ adj₁.counit ▷ (f₂ ≫ g₂)) ▷ g₁ ⊗≫ adj₂.counit ▷ (g₂ ≫ g₁) ⊗≫ 𝟙 _ := by - simp [bicategoricalComp]; coherence + dsimp only [compUnit, compCounit]; bicategory _ = 𝟙 _ ⊗≫ g₂ ◁ (rightZigzag adj₁.unit adj₁.counit) ⊗≫ (rightZigzag adj₂.unit adj₂.counit) ▷ g₁ ⊗≫ 𝟙 _ := by - rw [whisker_exchange]; simp [bicategoricalComp]; coherence + rw [whisker_exchange]; bicategory _ = _ := by - simp_rw [right_triangle]; simp [bicategoricalComp] + simp_rw [right_triangle]; bicategory /-- Composition of adjunctions. -/ @[simps] @@ -177,15 +165,13 @@ noncomputable section variable (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) /-- The isomorphism version of `leftZigzag`. -/ -def leftZigzagIso (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) := +abbrev leftZigzagIso (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) := whiskerRightIso η f ≪⊗≫ whiskerLeftIso f ε /-- The isomorphism version of `rightZigzag`. -/ -def rightZigzagIso (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) := +abbrev rightZigzagIso (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) := whiskerLeftIso g η ≪⊗≫ whiskerRightIso ε g -attribute [local simp] leftZigzagIso rightZigzagIso leftZigzag rightZigzag - @[simp] theorem leftZigzagIso_hom : (leftZigzagIso η ε).hom = leftZigzag η.hom ε.hom := rfl @@ -218,7 +204,7 @@ theorem right_triangle_of_left_triangle (h : leftZigzag η.hom ε.hom = (λ_ f). rightZigzag η.hom ε.hom = (ρ_ g).hom ≫ (λ_ g).inv := by rw [← cancel_epi (rightZigzag η.hom ε.hom ≫ (λ_ g).hom ≫ (ρ_ g).inv)] calc - _ = rightZigzag η.hom ε.hom ⊗≫ rightZigzag η.hom ε.hom := by coherence + _ = rightZigzag η.hom ε.hom ⊗≫ rightZigzag η.hom ε.hom := by bicategory _ = rightZigzag η.hom ε.hom := rightZigzag_idempotent_of_left_triangle _ _ h _ = _ := by simp @@ -233,15 +219,15 @@ theorem adjointifyCounit_left_triangle (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f calc _ = 𝟙 _ ⊗≫ (η.hom ▷ (f ≫ 𝟙 b) ≫ (f ≫ g) ◁ f ◁ ε.inv) ⊗≫ f ◁ g ◁ η.inv ▷ f ⊗≫ f ◁ ε.hom := by - simp [bicategoricalComp]; coherence + bicategory _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.hom ▷ (f ≫ g) ≫ (f ≫ g) ◁ η.inv) ▷ f ⊗≫ f ◁ ε.hom := by - rw [← whisker_exchange η.hom (f ◁ ε.inv)]; simp [bicategoricalComp]; coherence + rw [← whisker_exchange η.hom (f ◁ ε.inv)]; bicategory _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.inv ≫ η.hom) ▷ f ⊗≫ f ◁ ε.hom := by - rw [← whisker_exchange η.hom η.inv]; coherence + rw [← whisker_exchange η.hom η.inv]; bicategory _ = 𝟙 _ ⊗≫ f ◁ (ε.inv ≫ ε.hom) := by - rw [Iso.inv_hom_id]; simp [bicategoricalComp] + rw [Iso.inv_hom_id]; bicategory _ = _ := by - rw [Iso.inv_hom_id]; simp [bicategoricalComp] + rw [Iso.inv_hom_id]; bicategory /-- Adjoint equivalences between two objects. -/ structure Equivalence (a b : B) where diff --git a/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean b/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean index f35b3606bbc88..d4ec2116851e0 100644 --- a/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean +++ b/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean @@ -29,8 +29,6 @@ similar results for right Kan extensions and right Kan lifts. namespace CategoryTheory -open Mathlib.Tactic.BicategoryCoherence bicategoricalComp - namespace Bicategory universe w v u @@ -49,11 +47,13 @@ def Adjunction.isAbsoluteLeftKan {f : a ⟶ b} {u : b ⟶ a} (adj : f ⊣ u) : (𝟙 _ ⊗≫ u ◁ s.unit ⊗≫ adj.counit ▷ s.extension ⊗≫ 𝟙 _ : u ≫ h ⟶ s.extension) <| calc _ _ = 𝟙 _ ⊗≫ (adj.unit ▷ _ ≫ _ ◁ s.unit) ⊗≫ f ◁ adj.counit ▷ s.extension ⊗≫ 𝟙 _ := by - simp [bicategoricalComp] + dsimp only [whisker_extension, StructuredArrow.mk_right, whisker_unit, + StructuredArrow.mk_hom_eq_self] + bicategory _ = 𝟙 _ ⊗≫ s.unit ⊗≫ leftZigzag adj.unit adj.counit ▷ s.extension ⊗≫ 𝟙 _ := by - rw [← whisker_exchange, leftZigzag]; simp [bicategoricalComp] + rw [← whisker_exchange]; bicategory _ = s.unit := by - rw [adj.left_triangle]; simp [bicategoricalComp]) <| by + rw [adj.left_triangle]; bicategory) <| by intro s τ₀ ext /- We need to specify the type of `τ` to use the notation `⊗≫`. -/ @@ -62,13 +62,13 @@ def Adjunction.isAbsoluteLeftKan {f : a ⟶ b} {u : b ⟶ a} (adj : f ⊣ u) : simpa [bicategoricalComp] using LeftExtension.w τ₀ calc τ _ = 𝟙 _ ⊗≫ rightZigzag adj.unit adj.counit ▷ h ⊗≫ τ ⊗≫ 𝟙 _ := by - rw [adj.right_triangle]; simp [bicategoricalComp] + rw [adj.right_triangle]; bicategory _ = 𝟙 _ ⊗≫ u ◁ adj.unit ▷ h ⊗≫ (adj.counit ▷ _ ≫ _ ◁ τ) ⊗≫ 𝟙 _ := by - rw [rightZigzag]; simp [bicategoricalComp] + rw [rightZigzag]; bicategory _ = 𝟙 _ ⊗≫ u ◁ (adj.unit ▷ h ⊗≫ f ◁ τ) ⊗≫ adj.counit ▷ s.extension ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; simp [bicategoricalComp] + rw [← whisker_exchange]; bicategory _ = _ := by - rw [hτ]; simp [bicategoricalComp] + rw [hτ]; dsimp only [StructuredArrow.homMk_right] /-- A left Kan extension of the identity along `f` such that `f` commutes with is a right adjoint to `f`. The unit of this adjoint is given by the unit of the Kan extension. -/ @@ -86,13 +86,13 @@ def LeftExtension.IsKan.adjunction {f : a ⟶ b} {t : LeftExtension f (𝟙 a)} apply H.hom_ext calc _ _ = 𝟙 _ ⊗≫ t.unit ⊗≫ f ◁ rightZigzag t.unit ε ⊗≫ 𝟙 _ := by - simp [bicategoricalComp] + bicategory _ = 𝟙 _ ⊗≫ (t.unit ▷ _ ≫ _ ◁ t.unit) ⊗≫ f ◁ ε ▷ t.extension ⊗≫ 𝟙 _ := by - rw [rightZigzag]; simp [bicategoricalComp] + rw [rightZigzag]; bicategory _ = 𝟙 _ ⊗≫ t.unit ⊗≫ (t.unit ▷ f ⊗≫ f ◁ ε) ▷ t.extension ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; simp [bicategoricalComp] + rw [← whisker_exchange]; bicategory _ = _ := by - rw [← leftZigzag, Hε]; simp [bicategoricalComp] } + rw [← leftZigzag, Hε]; bicategory } /-- For an adjuntion `f ⊣ u`, `u` is a left Kan extension of the identity along `f`. The unit of this Kan extension is given by the unit of the adjunction. -/ @@ -130,11 +130,13 @@ def Adjunction.isAbsoluteLeftKanLift {f : a ⟶ b} {u : b ⟶ a} (adj : f ⊣ u) (𝟙 _ ⊗≫ s.unit ▷ f ⊗≫ s.lift ◁ adj.counit ⊗≫ 𝟙 _ : h ≫ f ⟶ s.lift) <| calc _ _ = 𝟙 _ ⊗≫ (_ ◁ adj.unit ≫ s.unit ▷ _) ⊗≫ s.lift ◁ adj.counit ▷ u ⊗≫ 𝟙 _ := by - simp [bicategoricalComp] + dsimp only [whisker_lift, StructuredArrow.mk_right, whisker_unit, + StructuredArrow.mk_hom_eq_self] + bicategory _ = s.unit ⊗≫ s.lift ◁ (rightZigzag adj.unit adj.counit) ⊗≫ 𝟙 _ := by - rw [whisker_exchange, rightZigzag]; simp [bicategoricalComp] + rw [whisker_exchange, rightZigzag]; bicategory _ = s.unit := by - rw [adj.right_triangle]; simp [bicategoricalComp]) <| by + rw [adj.right_triangle]; bicategory) <| by intro s τ₀ ext /- We need to specify the type of `τ` to use the notation `⊗≫`. -/ @@ -142,13 +144,13 @@ def Adjunction.isAbsoluteLeftKanLift {f : a ⟶ b} {u : b ⟶ a} (adj : f ⊣ u) have hτ : h ◁ adj.unit ⊗≫ τ ▷ u = s.unit := by simpa [bicategoricalComp] using LeftLift.w τ₀ calc τ _ = 𝟙 _ ⊗≫ h ◁ leftZigzag adj.unit adj.counit ⊗≫ τ ⊗≫ 𝟙 _ := by - rw [adj.left_triangle]; simp [bicategoricalComp] + rw [adj.left_triangle]; bicategory _ = 𝟙 _ ⊗≫ h ◁ adj.unit ▷ f ⊗≫ (_ ◁ adj.counit ≫ τ ▷ _) ⊗≫ 𝟙 _ := by - rw [leftZigzag]; simp [bicategoricalComp] + rw [leftZigzag]; bicategory _ = 𝟙 _ ⊗≫ (h ◁ adj.unit ⊗≫ τ ▷ u) ▷ f ⊗≫ s.lift ◁ adj.counit ⊗≫ 𝟙 _ := by - rw [whisker_exchange]; simp [bicategoricalComp] + rw [whisker_exchange]; bicategory _ = _ := by - rw [hτ]; simp [bicategoricalComp] + rw [hτ]; dsimp only [StructuredArrow.homMk_right] /-- A left Kan lift of the identity along `u` such that `u` commutes with is a left adjoint to `u`. The unit of this adjoint is given by the unit of the Kan lift. -/ @@ -165,13 +167,13 @@ def LeftLift.IsKan.adjunction {u : b ⟶ a} {t : LeftLift u (𝟙 a)} apply H.hom_ext calc _ _ = 𝟙 _ ⊗≫ t.unit ⊗≫ leftZigzag t.unit ε ▷ u ⊗≫ 𝟙 _ := by - simp [bicategoricalComp] + bicategory _ = 𝟙 _ ⊗≫ (_ ◁ t.unit ≫ t.unit ▷ _) ⊗≫ t.lift ◁ ε ▷ u ⊗≫ 𝟙 _ := by - rw [leftZigzag]; simp [bicategoricalComp] + rw [leftZigzag]; bicategory _ = 𝟙 _ ⊗≫ t.unit ⊗≫ t.lift ◁ (u ◁ t.unit ⊗≫ ε ▷ u) ⊗≫ 𝟙 _ := by - rw [whisker_exchange]; simp [bicategoricalComp] + rw [whisker_exchange]; bicategory _ = _ := by - rw [← rightZigzag, Hε]; simp [bicategoricalComp] + rw [← rightZigzag, Hε]; bicategory right_triangle := Hε } /-- For an adjuntion `f ⊣ u`, `f` is a left Kan lift of the identity along `u`. @@ -210,18 +212,28 @@ def isKanOfWhiskerLeftAdjoint .mk (fun s ↦ let k := s.extension let θ := s.unit - let τ : t.extension ⟶ k ≫ u := H.desc (.mk _ <| 𝟙 _ ⊗≫ g ◁ η' ⊗≫ θ ▷ u ⊗≫ 𝟙 _) - let σ : t.extension ≫ h ⟶ k := H'.desc <| (.mk _ <| (ρ_ _).hom ≫ τ) + let sτ := LeftExtension.mk _ <| 𝟙 _ ⊗≫ g ◁ η' ⊗≫ θ ▷ u ⊗≫ 𝟙 _ + let τ : t.extension ⟶ k ≫ u := H.desc sτ + let sσ := LeftLift.mk _ <| (ρ_ _).hom ≫ τ + let σ : t.extension ≫ h ⟶ k := H'.desc sσ LeftExtension.homMk σ <| (H' g).hom_ext <| by have Hσ : t.extension ◁ η' ⊗≫ σ ▷ u = 𝟙 _ ⊗≫ τ := by simpa [bicategoricalComp] using (H' _).fac (.mk _ <| (ρ_ _).hom ≫ τ) + dsimp only [LeftLift.whisker_lift, StructuredArrow.mk_right, LeftLift.whisker_unit, + StructuredArrow.mk_hom_eq_self, whisker_extension, whisker_unit] calc _ - _ = 𝟙 _ ⊗≫ (g ◁ η' ≫ t.unit ▷ (h ≫ u)) ⊗≫ f ◁ σ ▷ u ⊗≫ 𝟙 _ := by - simp [bicategoricalComp] - _ = 𝟙 _ ⊗≫ t.unit ▷ (𝟙 c) ⊗≫ f ◁ (t.extension ◁ η' ⊗≫ σ ▷ u) ⊗≫ 𝟙 _ := by - rw [whisker_exchange]; simp [bicategoricalComp] + _ = (g ◁ η' ≫ t.unit ▷ (h ≫ u)) ⊗≫ f ◁ σ ▷ u ⊗≫ 𝟙 _ := by + bicategory + _ = t.unit ▷ (𝟙 c) ⊗≫ f ◁ (t.extension ◁ η' ⊗≫ σ ▷ u) ⊗≫ 𝟙 _ := by + rw [whisker_exchange]; bicategory + _ = (ρ_ g).hom ≫ t.unit ≫ f ◁ H.desc sτ ≫ (α_ f s.extension u).inv := by + rw [Hσ] + dsimp only [τ] + bicategory _ = _ := by - rw [Hσ]; simp [τ, bicategoricalComp]) <| by + rw [IsKan.fac_assoc] + dsimp only [StructuredArrow.mk_right, StructuredArrow.mk_hom_eq_self, sτ] + bicategory) <| by intro s' τ₀' let τ' : t.extension ≫ h ⟶ s'.extension := τ₀'.right have Hτ' : t.unit ▷ h ⊗≫ f ◁ τ' = s'.unit := by simpa [bicategoricalComp] using τ₀'.w.symm @@ -231,13 +243,20 @@ def isKanOfWhiskerLeftAdjoint rw [(H' _).fac] apply (cancel_epi (ρ_ _).inv).mp apply H.hom_ext + dsimp only [LeftLift.whisker_lift, StructuredArrow.mk_right, LeftLift.whisker_unit, + StructuredArrow.mk_hom_eq_self] + let σs' := LeftExtension.mk (s'.extension ≫ u) + (𝟙 g ⊗≫ g ◁ η' ⊗≫ s'.unit ▷ u ⊗≫ 𝟙 (f ≫ s'.extension ≫ u)) calc _ _ = 𝟙 _ ⊗≫ (t.unit ▷ (𝟙 c) ≫ (f ≫ t.extension) ◁ η') ⊗≫ f ◁ τ' ▷ u := by - simp [bicategoricalComp] + bicategory _ = 𝟙 g ⊗≫ g ◁ η' ⊗≫ (t.unit ▷ h ⊗≫ f ◁ τ') ▷ u ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; simp [bicategoricalComp] + rw [← whisker_exchange]; bicategory + _ = t.unit ≫ f ◁ H.desc σs' := by + rw [Hτ', IsKan.fac] + dsimp only [StructuredArrow.mk_hom_eq_self, σs'] _ = _ := by - rw [Hτ']; simp [bicategoricalComp] + bicategory instance {f : a ⟶ b} {g : a ⟶ c} {x : B} {h : c ⟶ x} [IsLeftAdjoint h] [HasLeftKanExtension f g] : Lan.CommuteWith f g h := diff --git a/Mathlib/CategoryTheory/Monoidal/Bimod.lean b/Mathlib/CategoryTheory/Monoidal/Bimod.lean index a29f338d9a4d7..23401b5af6406 100644 --- a/Mathlib/CategoryTheory/Monoidal/Bimod.lean +++ b/Mathlib/CategoryTheory/Monoidal/Bimod.lean @@ -201,13 +201,13 @@ noncomputable def actLeft : R.X ⊗ X P Q ⟶ X P Q := simp only [Category.assoc] slice_lhs 1 2 => rw [associator_inv_naturality_middle] slice_rhs 3 4 => rw [← comp_whiskerRight, middle_assoc, comp_whiskerRight] - coherence) + monoidal) (by dsimp slice_lhs 1 1 => rw [MonoidalCategory.whiskerLeft_comp] slice_lhs 2 3 => rw [associator_inv_naturality_right] slice_lhs 3 4 => rw [whisker_exchange] - coherence)) + monoidal)) theorem whiskerLeft_π_actLeft : (R.X ◁ coequalizer.π _ _) ≫ actLeft P Q = @@ -224,7 +224,7 @@ theorem one_act_left' : (R.one ▷ _) ≫ actLeft P Q = (λ_ _).hom := by slice_lhs 1 2 => rw [associator_inv_naturality_left] slice_lhs 2 3 => rw [← comp_whiskerRight, one_actLeft] slice_rhs 1 2 => rw [leftUnitor_naturality] - coherence + monoidal theorem left_assoc' : (R.mul ▷ _) ≫ actLeft P Q = (α_ R.X R.X _).hom ≫ (R.X ◁ actLeft P Q) ≫ actLeft P Q := by @@ -240,7 +240,7 @@ theorem left_assoc' : MonoidalCategory.whiskerLeft_comp, MonoidalCategory.whiskerLeft_comp] slice_rhs 4 5 => rw [whiskerLeft_π_actLeft] slice_rhs 3 4 => rw [associator_inv_naturality_middle] - coherence + monoidal end @@ -484,7 +484,7 @@ theorem hom_left_act_hom' : slice_rhs 3 4 => erw [TensorBimod.whiskerLeft_π_actLeft P (Q.tensorBimod L)] slice_rhs 2 3 => erw [associator_inv_naturality_right] slice_rhs 3 4 => erw [whisker_exchange] - coherence + monoidal theorem hom_right_act_hom' : ((P.tensorBimod Q).tensorBimod L).actRight ≫ hom P Q L = @@ -510,7 +510,7 @@ theorem hom_right_act_hom' : slice_rhs 3 4 => rw [← MonoidalCategory.whiskerLeft_comp, TensorBimod.π_tensor_id_actRight, MonoidalCategory.whiskerLeft_comp, MonoidalCategory.whiskerLeft_comp] - coherence + monoidal /-- An auxiliary morphism for the definition of the underlying morphism of the inverse component of the associator isomorphism. -/ @@ -529,7 +529,7 @@ noncomputable def invAux : P.X ⊗ (Q.tensorBimod L).X ⟶ ((P.tensorBimod Q).te slice_rhs 1 2 => rw [MonoidalCategory.whiskerLeft_comp] slice_rhs 2 3 => rw [associator_inv_naturality_right] slice_rhs 3 4 => rw [whisker_exchange] - coherence) + monoidal) /-- The underlying morphism of the inverse component of the associator isomorphism. -/ noncomputable def inv : @@ -550,7 +550,7 @@ noncomputable def inv : MonoidalCategory.whiskerLeft_comp, MonoidalCategory.whiskerLeft_comp] slice_rhs 4 6 => rw [id_tensor_π_preserves_coequalizer_inv_desc] slice_rhs 3 4 => rw [associator_inv_naturality_middle] - coherence) + monoidal) theorem hom_inv_id : hom P Q L ≫ inv P Q L = 𝟙 _ := by dsimp [hom, homAux, inv, invAux] @@ -605,7 +605,7 @@ theorem hom_inv_id : hom P ≫ inv P = 𝟙 _ := by slice_lhs 2 3 => rw [associator_inv_naturality_left] slice_lhs 3 4 => rw [← comp_whiskerRight, Mon_.one_mul] slice_rhs 1 2 => rw [Category.comp_id] - coherence + monoidal theorem inv_hom_id : inv P ≫ hom P = 𝟙 _ := by dsimp [hom, inv] @@ -659,7 +659,7 @@ theorem hom_inv_id : hom P ≫ inv P = 𝟙 _ := by slice_lhs 2 3 => rw [associator_naturality_right] slice_lhs 3 4 => rw [← MonoidalCategory.whiskerLeft_comp, Mon_.mul_one] slice_rhs 1 2 => rw [Category.comp_id] - coherence + monoidal theorem inv_hom_id : inv P ≫ hom P = 𝟙 _ := by dsimp [hom, inv] @@ -764,7 +764,7 @@ theorem id_whiskerLeft_bimod {X Y : Mon_ C} {M N : Bimod X Y} (f : M ⟶ N) : slice_rhs 3 4 => rw [associator_inv_naturality_left] slice_rhs 4 5 => rw [← comp_whiskerRight, Mon_.one_mul] have : (λ_ (X.X ⊗ N.X)).inv ≫ (α_ (𝟙_ C) X.X N.X).inv ≫ ((λ_ X.X).hom ▷ N.X) = 𝟙 _ := by - coherence + monoidal slice_rhs 2 4 => rw [this] slice_rhs 1 2 => rw [Category.comp_id] @@ -926,7 +926,7 @@ theorem pentagon_bimod {V W X Y Z : Mon_ C} (M : Bimod V W) (N : Bimod W X) (P : rw [← whisker_exchange] slice_rhs 3 5 => rw [π_tensor_id_preserves_coequalizer_inv_desc] slice_rhs 2 3 => rw [associator_naturality_right] - coherence + monoidal theorem triangle_bimod {X Y Z : Mon_ C} (M : Bimod X Y) (N : Bimod Y Z) : (associatorBimod M (regular Y) N).hom ≫ whiskerLeft M (leftUnitorBimod N).hom = diff --git a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean index 910935ef1ea15..27f88cae42c31 100644 --- a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean @@ -6,7 +6,7 @@ Authors: Scott Morrison import Mathlib.CategoryTheory.Monoidal.Discrete import Mathlib.CategoryTheory.Monoidal.NaturalTransformation import Mathlib.CategoryTheory.Monoidal.Opposite -import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Monoidal.Basic import Mathlib.CategoryTheory.CommSq /-! @@ -153,7 +153,7 @@ theorem yang_baxter' (X Y Z : C) : 𝟙 _ ⊗≫ (X ◁ (β_ Y Z).hom ⊗≫ (β_ X Z).hom ▷ Y ⊗≫ Z ◁ (β_ X Y).hom) ⊗≫ 𝟙 _ := by rw [← cancel_epi (α_ X Y Z).inv, ← cancel_mono (α_ Z Y X).hom] convert yang_baxter X Y Z using 1 - all_goals coherence + all_goals monoidal theorem yang_baxter_iso (X Y Z : C) : (α_ X Y Z).symm ≪≫ whiskerRightIso (β_ X Y) Z ≪≫ α_ Y X Z ≪≫ @@ -262,14 +262,14 @@ theorem braiding_leftUnitor_aux₁ (X : C) : (α_ (𝟙_ C) (𝟙_ C) X).hom ≫ (𝟙_ C ◁ (β_ X (𝟙_ C)).inv) ≫ (α_ _ X _).inv ≫ ((λ_ X).hom ▷ _) = ((λ_ _).hom ▷ X) ≫ (β_ X (𝟙_ C)).inv := by - coherence + monoidal theorem braiding_leftUnitor_aux₂ (X : C) : ((β_ X (𝟙_ C)).hom ▷ 𝟙_ C) ≫ ((λ_ X).hom ▷ 𝟙_ C) = (ρ_ X).hom ▷ 𝟙_ C := calc ((β_ X (𝟙_ C)).hom ▷ 𝟙_ C) ≫ ((λ_ X).hom ▷ 𝟙_ C) = ((β_ X (𝟙_ C)).hom ▷ 𝟙_ C) ≫ (α_ _ _ _).hom ≫ (α_ _ _ _).inv ≫ ((λ_ X).hom ▷ 𝟙_ C) := by - coherence + monoidal _ = ((β_ X (𝟙_ C)).hom ▷ 𝟙_ C) ≫ (α_ _ _ _).hom ≫ (_ ◁ (β_ X _).hom) ≫ (_ ◁ (β_ X _).inv) ≫ (α_ _ _ _).inv ≫ ((λ_ X).hom ▷ 𝟙_ C) := by simp @@ -291,14 +291,14 @@ theorem braiding_rightUnitor_aux₁ (X : C) : (α_ X (𝟙_ C) (𝟙_ C)).inv ≫ ((β_ (𝟙_ C) X).inv ▷ 𝟙_ C) ≫ (α_ _ X _).hom ≫ (_ ◁ (ρ_ X).hom) = (X ◁ (ρ_ _).hom) ≫ (β_ (𝟙_ C) X).inv := by - coherence + monoidal theorem braiding_rightUnitor_aux₂ (X : C) : (𝟙_ C ◁ (β_ (𝟙_ C) X).hom) ≫ (𝟙_ C ◁ (ρ_ X).hom) = 𝟙_ C ◁ (λ_ X).hom := calc (𝟙_ C ◁ (β_ (𝟙_ C) X).hom) ≫ (𝟙_ C ◁ (ρ_ X).hom) = (𝟙_ C ◁ (β_ (𝟙_ C) X).hom) ≫ (α_ _ _ _).inv ≫ (α_ _ _ _).hom ≫ (𝟙_ C ◁ (ρ_ X).hom) := by - coherence + monoidal _ = (𝟙_ C ◁ (β_ (𝟙_ C) X).hom) ≫ (α_ _ _ _).inv ≫ ((β_ _ X).hom ▷ _) ≫ ((β_ _ X).inv ▷ _) ≫ (α_ _ _ _).hom ≫ (𝟙_ C ◁ (ρ_ X).hom) := by simp @@ -324,7 +324,7 @@ theorem braiding_tensorUnit_left (X : C) : (β_ (𝟙_ C) X).hom = (λ_ X).hom theorem braiding_inv_tensorUnit_left (X : C) : (β_ (𝟙_ C) X).inv = (ρ_ X).hom ≫ (λ_ X).inv := by rw [Iso.inv_ext] rw [braiding_tensorUnit_left] - coherence + monoidal @[reassoc] theorem leftUnitor_inv_braiding (X : C) : (λ_ X).inv ≫ (β_ (𝟙_ C) X).hom = (ρ_ X).inv := by @@ -343,7 +343,7 @@ theorem braiding_tensorUnit_right (X : C) : (β_ X (𝟙_ C)).hom = (ρ_ X).hom theorem braiding_inv_tensorUnit_right (X : C) : (β_ X (𝟙_ C)).inv = (λ_ X).hom ≫ (ρ_ X).inv := by rw [Iso.inv_ext] rw [braiding_tensorUnit_right] - coherence + monoidal end @@ -551,7 +551,7 @@ theorem tensor_left_unitality (X₁ X₂ : C) : ((λ_ (𝟙_ C)).inv ▷ (X₁ ⊗ X₂)) ≫ (α_ (𝟙_ C) (𝟙_ C) (X₁ ⊗ X₂)).hom ≫ (𝟙_ C ◁ (α_ (𝟙_ C) X₁ X₂).inv) = 𝟙_ C ◁ (λ_ X₁).inv ▷ X₂ := by - coherence + monoidal slice_rhs 1 3 => rw [this] clear this slice_rhs 1 2 => rw [← MonoidalCategory.whiskerLeft_comp, ← comp_whiskerRight, @@ -568,30 +568,26 @@ theorem tensor_right_unitality (X₁ X₂ : C) : ((X₁ ⊗ X₂) ◁ (λ_ (𝟙_ C)).inv) ≫ (α_ X₁ X₂ (𝟙_ C ⊗ 𝟙_ C)).hom ≫ (X₁ ◁ (α_ X₂ (𝟙_ C) (𝟙_ C)).inv) = (α_ X₁ X₂ (𝟙_ C)).hom ≫ (X₁ ◁ (ρ_ X₂).inv ▷ 𝟙_ C) := by - coherence + monoidal slice_rhs 1 3 => rw [this] clear this slice_rhs 2 3 => rw [← MonoidalCategory.whiskerLeft_comp, ← comp_whiskerRight, rightUnitor_inv_braiding] simp [tensorHom_id, id_tensorHom, tensorHom_def] +@[reassoc] theorem tensor_associativity (X₁ X₂ Y₁ Y₂ Z₁ Z₂ : C) : (tensor_μ X₁ X₂ Y₁ Y₂ ▷ (Z₁ ⊗ Z₂)) ≫ tensor_μ (X₁ ⊗ Y₁) (X₂ ⊗ Y₂) Z₁ Z₂ ≫ ((α_ X₁ Y₁ Z₁).hom ⊗ (α_ X₂ Y₂ Z₂).hom) = (α_ (X₁ ⊗ X₂) (Y₁ ⊗ Y₂) (Z₁ ⊗ Z₂)).hom ≫ ((X₁ ⊗ X₂) ◁ tensor_μ Y₁ Y₂ Z₁ Z₂) ≫ tensor_μ X₁ X₂ (Y₁ ⊗ Z₁) (Y₂ ⊗ Z₂) := by dsimp only [tensor_obj, prodMonoidal_tensorObj, tensor_μ] - simp only [whiskerRight_tensor, comp_whiskerRight, whisker_assoc, assoc, Iso.inv_hom_id_assoc, - tensor_whiskerLeft, braiding_tensor_left, MonoidalCategory.whiskerLeft_comp, - braiding_tensor_right] + simp only [braiding_tensor_left, braiding_tensor_right] calc _ = 𝟙 _ ⊗≫ X₁ ◁ ((β_ X₂ Y₁).hom ▷ (Y₂ ⊗ Z₁) ≫ (Y₁ ⊗ X₂) ◁ (β_ Y₂ Z₁).hom) ▷ Z₂ ⊗≫ - X₁ ◁ Y₁ ◁ (β_ X₂ Z₁).hom ▷ Y₂ ▷ Z₂ ⊗≫ 𝟙 _ := by coherence - _ = _ := by rw [← whisker_exchange]; coherence - --- We got a timeout if `reassoc` was at the declaration, so we put it here instead. -attribute [reassoc] tensor_associativity + X₁ ◁ Y₁ ◁ (β_ X₂ Z₁).hom ▷ Y₂ ▷ Z₂ ⊗≫ 𝟙 _ := by monoidal + _ = _ := by rw [← whisker_exchange]; monoidal /-- The tensor product functor from `C × C` to `C` as a monoidal functor. -/ @[simps!] @@ -621,11 +617,10 @@ theorem leftUnitor_monoidal (X₁ X₂ : C) : (λ_ X₁).hom ⊗ (λ_ X₂).hom = (α_ (𝟙_ C) X₁ (𝟙_ C ⊗ X₂)).hom ≫ (𝟙_ C ◁ (α_ X₁ (𝟙_ C) X₂).inv) ≫ (λ_ ((X₁ ⊗ 𝟙_ C) ⊗ X₂)).hom ≫ ((ρ_ X₁).hom ▷ X₂) := by - coherence + monoidal rw [this]; clear this rw [← braiding_leftUnitor] - dsimp only [tensor_obj, prodMonoidal_tensorObj] - coherence + monoidal @[reassoc] theorem rightUnitor_monoidal (X₁ X₂ : C) : @@ -636,11 +631,10 @@ theorem rightUnitor_monoidal (X₁ X₂ : C) : (ρ_ X₁).hom ⊗ (ρ_ X₂).hom = (α_ X₁ (𝟙_ C) (X₂ ⊗ 𝟙_ C)).hom ≫ (X₁ ◁ (α_ (𝟙_ C) X₂ (𝟙_ C)).inv) ≫ (X₁ ◁ (ρ_ (𝟙_ C ⊗ X₂)).hom) ≫ (X₁ ◁ (λ_ X₂).hom) := by - coherence + monoidal rw [this]; clear this rw [← braiding_rightUnitor] - dsimp only [tensor_obj, prodMonoidal_tensorObj] - coherence + monoidal theorem associator_monoidal (X₁ X₂ X₃ Y₁ Y₂ Y₃ : C) : tensor_μ (X₁ ⊗ X₂) X₃ (Y₁ ⊗ Y₂) Y₃ ≫ @@ -651,8 +645,9 @@ theorem associator_monoidal (X₁ X₂ X₃ Y₁ Y₂ Y₃ : C) : calc _ = 𝟙 _ ⊗≫ X₁ ◁ X₂ ◁ (β_ X₃ Y₁).hom ▷ Y₂ ▷ Y₃ ⊗≫ X₁ ◁ ((X₂ ⊗ Y₁) ◁ (β_ X₃ Y₂).hom ≫ - (β_ X₂ Y₁).hom ▷ (Y₂ ⊗ X₃)) ▷ Y₃ ⊗≫ 𝟙 _ := by simp; coherence - _ = _ := by rw [whisker_exchange]; simp; coherence + (β_ X₂ Y₁).hom ▷ (Y₂ ⊗ X₃)) ▷ Y₃ ⊗≫ 𝟙 _ := by + rw [braiding_tensor_right]; monoidal + _ = _ := by rw [whisker_exchange, braiding_tensor_left]; monoidal -- We got a timeout if `reassoc` was at the declaration, so we put it here instead. attribute [reassoc] associator_monoidal diff --git a/Mathlib/CategoryTheory/Monoidal/Center.lean b/Mathlib/CategoryTheory/Monoidal/Center.lean index 4d27a6af5c4be..19df47cf77e91 100644 --- a/Mathlib/CategoryTheory/Monoidal/Center.lean +++ b/Mathlib/CategoryTheory/Monoidal/Center.lean @@ -137,19 +137,19 @@ def tensorObj (X Y : Center C) : Center C := X.1 ◁ (HalfBraiding.β Y.2 U).hom ▷ U' ⊗≫ (_ ◁ (HalfBraiding.β Y.2 U').hom ≫ (HalfBraiding.β X.2 U).hom ▷ _) ⊗≫ - U ◁ (HalfBraiding.β X.2 U').hom ▷ Y.1 ⊗≫ 𝟙 _ := by coherence - _ = _ := by rw [whisker_exchange]; coherence + U ◁ (HalfBraiding.β X.2 U').hom ▷ Y.1 ⊗≫ 𝟙 _ := by monoidal + _ = _ := by rw [whisker_exchange]; monoidal naturality := fun {U U'} f => by dsimp only [Iso.trans_hom, whiskerLeftIso_hom, Iso.symm_hom, whiskerRightIso_hom] calc _ = 𝟙 _ ⊗≫ (X.1 ◁ (Y.1 ◁ f ≫ (HalfBraiding.β Y.2 U').hom)) ⊗≫ - (HalfBraiding.β X.2 U').hom ▷ Y.1 ⊗≫ 𝟙 _ := by coherence + (HalfBraiding.β X.2 U').hom ▷ Y.1 ⊗≫ 𝟙 _ := by monoidal _ = 𝟙 _ ⊗≫ X.1 ◁ (HalfBraiding.β Y.2 U).hom ⊗≫ (X.1 ◁ f ≫ (HalfBraiding.β X.2 U').hom) ▷ Y.1 ⊗≫ 𝟙 _ := by - rw [HalfBraiding.naturality]; coherence - _ = _ := by rw [HalfBraiding.naturality]; coherence }⟩ + rw [HalfBraiding.naturality]; monoidal + _ = _ := by rw [HalfBraiding.naturality]; monoidal }⟩ @[reassoc] theorem whiskerLeft_comm (X : Center C) {Y₁ Y₂ : Center C} (f : Y₁ ⟶ Y₂) (U : C) : @@ -160,12 +160,12 @@ theorem whiskerLeft_comm (X : Center C) {Y₁ Y₂ : Center C} (f : Y₁ ⟶ Y calc _ = 𝟙 _ ⊗≫ X.fst ◁ (f.f ▷ U ≫ (HalfBraiding.β Y₂.snd U).hom) ⊗≫ - (HalfBraiding.β X.snd U).hom ▷ Y₂.fst ⊗≫ 𝟙 _ := by coherence + (HalfBraiding.β X.snd U).hom ▷ Y₂.fst ⊗≫ 𝟙 _ := by monoidal _ = 𝟙 _ ⊗≫ X.fst ◁ (HalfBraiding.β Y₁.snd U).hom ⊗≫ ((X.fst ⊗ U) ◁ f.f ≫ (HalfBraiding.β X.snd U).hom ▷ Y₂.fst) ⊗≫ 𝟙 _ := by - rw [f.comm]; coherence - _ = _ := by rw [whisker_exchange]; coherence + rw [f.comm]; monoidal + _ = _ := by rw [whisker_exchange]; monoidal /-- Auxiliary definition for the `MonoidalCategory` instance on `Center C`. -/ def whiskerLeft (X : Center C) {Y₁ Y₂ : Center C} (f : Y₁ ⟶ Y₂) : @@ -182,12 +182,12 @@ theorem whiskerRight_comm {X₁ X₂ : Center C} (f : X₁ ⟶ X₂) (Y : Center calc _ = 𝟙 _ ⊗≫ (f.f ▷ (Y.fst ⊗ U) ≫ X₂.fst ◁ (HalfBraiding.β Y.snd U).hom) ⊗≫ - (HalfBraiding.β X₂.snd U).hom ▷ Y.fst ⊗≫ 𝟙 _ := by coherence + (HalfBraiding.β X₂.snd U).hom ▷ Y.fst ⊗≫ 𝟙 _ := by monoidal _ = 𝟙 _ ⊗≫ X₁.fst ◁ (HalfBraiding.β Y.snd U).hom ⊗≫ (f.f ▷ U ≫ (HalfBraiding.β X₂.snd U).hom) ▷ Y.fst ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; coherence - _ = _ := by rw [f.comm]; coherence + rw [← whisker_exchange]; monoidal + _ = _ := by rw [f.comm]; monoidal /-- Auxiliary definition for the `MonoidalCategory` instance on `Center C`. -/ def whiskerRight {X₁ X₂ : Center C} (f : X₁ ⟶ X₂) (Y : Center C) : diff --git a/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean b/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean index 430680b7fe1cf..de0f9bff68b37 100644 --- a/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean +++ b/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Jendrusch, Scott Morrison, Bhavik Mehta, Jakob von Raumer -/ -import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence /-! # Lemmas which are consequences of monoidal coherence @@ -26,47 +26,47 @@ variable {C : Type*} [Category C] [MonoidalCategory C] @[reassoc] theorem leftUnitor_tensor'' (X Y : C) : (α_ (𝟙_ C) X Y).hom ≫ (λ_ (X ⊗ Y)).hom = (λ_ X).hom ⊗ 𝟙 Y := by - coherence + monoidal_coherence @[reassoc] theorem leftUnitor_tensor' (X Y : C) : (λ_ (X ⊗ Y)).hom = (α_ (𝟙_ C) X Y).inv ≫ ((λ_ X).hom ⊗ 𝟙 Y) := by - coherence + monoidal_coherence @[reassoc] theorem leftUnitor_tensor_inv' (X Y : C) : - (λ_ (X ⊗ Y)).inv = ((λ_ X).inv ⊗ 𝟙 Y) ≫ (α_ (𝟙_ C) X Y).hom := by coherence + (λ_ (X ⊗ Y)).inv = ((λ_ X).inv ⊗ 𝟙 Y) ≫ (α_ (𝟙_ C) X Y).hom := by monoidal_coherence @[reassoc] theorem id_tensor_rightUnitor_inv (X Y : C) : 𝟙 X ⊗ (ρ_ Y).inv = (ρ_ _).inv ≫ (α_ _ _ _).hom := by - coherence + monoidal_coherence @[reassoc] theorem leftUnitor_inv_tensor_id (X Y : C) : (λ_ X).inv ⊗ 𝟙 Y = (λ_ _).inv ≫ (α_ _ _ _).inv := by - coherence + monoidal_coherence @[reassoc] theorem pentagon_inv_inv_hom (W X Y Z : C) : (α_ W (X ⊗ Y) Z).inv ≫ ((α_ W X Y).inv ⊗ 𝟙 Z) ≫ (α_ (W ⊗ X) Y Z).hom = (𝟙 W ⊗ (α_ X Y Z).hom) ≫ (α_ W X (Y ⊗ Z)).inv := by - coherence + monoidal_coherence theorem unitors_equal : (λ_ (𝟙_ C)).hom = (ρ_ (𝟙_ C)).hom := by - coherence + monoidal_coherence theorem unitors_inv_equal : (λ_ (𝟙_ C)).inv = (ρ_ (𝟙_ C)).inv := by - coherence + monoidal_coherence @[reassoc] theorem pentagon_hom_inv {W X Y Z : C} : (α_ W X (Y ⊗ Z)).hom ≫ (𝟙 W ⊗ (α_ X Y Z).inv) = (α_ (W ⊗ X) Y Z).inv ≫ ((α_ W X Y).hom ⊗ 𝟙 Z) ≫ (α_ W (X ⊗ Y) Z).hom := by - coherence + monoidal_coherence @[reassoc] theorem pentagon_inv_hom (W X Y Z : C) : (α_ (W ⊗ X) Y Z).inv ≫ ((α_ W X Y).hom ⊗ 𝟙 Z) = (α_ W X (Y ⊗ Z)).hom ≫ (𝟙 W ⊗ (α_ X Y Z).inv) ≫ (α_ W (X ⊗ Y) Z).inv := by - coherence + monoidal_coherence end CategoryTheory.MonoidalCategory diff --git a/Mathlib/CategoryTheory/Monoidal/Comon_.lean b/Mathlib/CategoryTheory/Monoidal/Comon_.lean index 664bf0f4c25c5..61c63c58ac902 100644 --- a/Mathlib/CategoryTheory/Monoidal/Comon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Comon_.lean @@ -59,9 +59,9 @@ def trivial : Comon_ C where X := 𝟙_ C counit := 𝟙 _ comul := (λ_ _).inv - comul_assoc := by coherence - counit_comul := by coherence - comul_counit := by coherence + comul_assoc := by monoidal_coherence + counit_comul := by monoidal_coherence + comul_counit := by monoidal_coherence instance : Inhabited (Comon_ C) := ⟨trivial C⟩ diff --git a/Mathlib/CategoryTheory/Monoidal/Hopf_.lean b/Mathlib/CategoryTheory/Monoidal/Hopf_.lean index 12419c19a3575..4bf50784e7cc7 100644 --- a/Mathlib/CategoryTheory/Monoidal/Hopf_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Hopf_.lean @@ -223,7 +223,7 @@ theorem antipode_comul₂ (A : Hopf_ C) : MonoidalCategory.whiskerRight_id, whiskerLeft_rightUnitor, Category.assoc, Iso.hom_inv_id_assoc, Iso.inv_hom_id_assoc, whiskerLeft_inv_hom_assoc, antipode_right_assoc] rw [rightUnitor_inv_naturality_assoc, tensorHom_def] - coherence + monoidal theorem antipode_comul (A : Hopf_ C) : A.antipode ≫ A.X.comul.hom = A.X.comul.hom ≫ (β_ _ _).hom ≫ (A.antipode ⊗ A.antipode) := by @@ -400,7 +400,7 @@ theorem mul_antipode₂ (A : Hopf_ C) : slice_lhs 2 3 => rw [rightUnitor_naturality] simp only [Mon_.tensorUnit_X] - coherence + monoidal theorem mul_antipode (A : Hopf_ C) : A.X.X.mul ≫ A.antipode = (A.antipode ⊗ A.antipode) ≫ (β_ _ _).hom ≫ A.X.X.mul := by diff --git a/Mathlib/CategoryTheory/Monoidal/Mon_.lean b/Mathlib/CategoryTheory/Monoidal/Mon_.lean index d773481a2b2d8..292ec93b5a143 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mon_.lean @@ -57,8 +57,8 @@ def trivial : Mon_ C where X := 𝟙_ C one := 𝟙 _ mul := (λ_ _).hom - mul_assoc := by coherence - mul_one := by coherence + mul_assoc := by monoidal_coherence + mul_one := by monoidal_coherence instance : Inhabited (Mon_ C) := ⟨trivial C⟩ @@ -514,7 +514,7 @@ variable {C} theorem one_braiding {X Y : Mon_ C} : (X ⊗ Y).one ≫ (β_ X.X Y.X).hom = (Y ⊗ X).one := by simp only [monMonoidalStruct_tensorObj_X, tensor_one, Category.assoc, BraidedCategory.braiding_naturality, braiding_tensorUnit_right, Iso.cancel_iso_inv_left] - coherence + monoidal end BraidedCategory diff --git a/Mathlib/CategoryTheory/Monoidal/Opposite.lean b/Mathlib/CategoryTheory/Monoidal/Opposite.lean index cecef27b955d5..6d15b4c0add4f 100644 --- a/Mathlib/CategoryTheory/Monoidal/Opposite.lean +++ b/Mathlib/CategoryTheory/Monoidal/Opposite.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence /-! # Monoidal opposites @@ -160,8 +160,8 @@ instance monoidalCategoryOp : MonoidalCategory Cᵒᵖ where associator_naturality f g h := Quiver.Hom.unop_inj <| by simp leftUnitor_naturality f := Quiver.Hom.unop_inj <| by simp rightUnitor_naturality f := Quiver.Hom.unop_inj <| by simp - triangle X Y := Quiver.Hom.unop_inj <| by dsimp; coherence - pentagon W X Y Z := Quiver.Hom.unop_inj <| by dsimp; coherence + triangle X Y := Quiver.Hom.unop_inj <| by dsimp; monoidal_coherence + pentagon W X Y Z := Quiver.Hom.unop_inj <| by dsimp; monoidal_coherence section OppositeLemmas @@ -241,7 +241,7 @@ instance monoidalCategoryMop : MonoidalCategory Cᴹᵒᵖ where rightUnitor_naturality f := Quiver.Hom.unmop_inj <| by simp -- Porting note: Changed `by coherence` to `by simp` below triangle X Y := Quiver.Hom.unmop_inj <| by simp - pentagon W X Y Z := Quiver.Hom.unmop_inj <| by dsimp; coherence + pentagon W X Y Z := Quiver.Hom.unmop_inj <| by dsimp; monoidal_coherence -- it would be nice if we could autogenerate all of these somehow section MonoidalOppositeLemmas diff --git a/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean index d5e3a652d624a..09afedcc3b9aa 100644 --- a/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Jakob von Raumer. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jakob von Raumer -/ -import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Monoidal.Basic import Mathlib.CategoryTheory.Closed.Monoidal import Mathlib.Tactic.ApplyFun @@ -128,8 +128,8 @@ attribute [reassoc (attr := simp)] ExactPairing.evaluation_coevaluation instance exactPairingUnit : ExactPairing (𝟙_ C) (𝟙_ C) where coevaluation' := (ρ_ _).inv evaluation' := (ρ_ _).hom - coevaluation_evaluation' := by rw [← id_tensorHom, ← tensorHom_id]; coherence - evaluation_coevaluation' := by rw [← id_tensorHom, ← tensorHom_id]; coherence + coevaluation_evaluation' := by monoidal_coherence + evaluation_coevaluation' := by monoidal_coherence /-- A class of objects which have a right dual. -/ class HasRightDual (X : C) where @@ -204,9 +204,9 @@ theorem rightAdjointMate_comp {X Y Z : C} [HasRightDual X] [HasRightDual Y] {f : _ ◁ η_ X (Xᘁ) ≫ _ ◁ (f ⊗ g) ≫ (α_ (Yᘁ) Y Z).inv ≫ ε_ Y (Yᘁ) ▷ _ ≫ (λ_ Z).hom := calc _ = 𝟙 _ ⊗≫ (Yᘁ : C) ◁ η_ X Xᘁ ≫ Yᘁ ◁ f ▷ Xᘁ ⊗≫ (ε_ Y Yᘁ ▷ Xᘁ ≫ 𝟙_ C ◁ g) ⊗≫ 𝟙 _ := by - dsimp only [rightAdjointMate]; coherence + dsimp only [rightAdjointMate]; monoidal _ = _ := by - rw [← whisker_exchange, tensorHom_def]; coherence + rw [← whisker_exchange, tensorHom_def]; monoidal theorem leftAdjointMate_comp {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] {f : X ⟶ Y} {g : (ᘁX) ⟶ Z} : @@ -215,9 +215,9 @@ theorem leftAdjointMate_comp {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] {f : X η_ (ᘁX : C) X ▷ _ ≫ (g ⊗ f) ▷ _ ≫ (α_ _ _ _).hom ≫ _ ◁ ε_ _ _ ≫ (ρ_ _).hom := calc _ = 𝟙 _ ⊗≫ η_ (ᘁX : C) X ▷ (ᘁY) ⊗≫ (ᘁX) ◁ f ▷ (ᘁY) ⊗≫ ((ᘁX) ◁ ε_ (ᘁY) Y ≫ g ▷ 𝟙_ C) ⊗≫ 𝟙 _ := by - dsimp only [leftAdjointMate]; coherence + dsimp only [leftAdjointMate]; monoidal _ = _ := by - rw [whisker_exchange, tensorHom_def']; coherence + rw [whisker_exchange, tensorHom_def']; monoidal /-- The composition of right adjoint mates is the adjoint mate of the composition. -/ @[reassoc] @@ -231,14 +231,14 @@ theorem comp_rightAdjointMate {X Y Z : C} [HasRightDual X] [HasRightDual Y] [Has calc _ = 𝟙 _ ⊗≫ (η_ Y Yᘁ ▷ 𝟙_ C ≫ (Y ⊗ Yᘁ) ◁ η_ X Xᘁ) ⊗≫ Y ◁ Yᘁ ◁ f ▷ Xᘁ ⊗≫ Y ◁ ε_ Y Yᘁ ▷ Xᘁ ⊗≫ g ▷ Xᘁ ⊗≫ 𝟙 _ := by - rw [tensorHom_def']; coherence + rw [tensorHom_def']; monoidal _ = η_ X Xᘁ ⊗≫ (η_ Y Yᘁ ▷ (X ⊗ Xᘁ) ≫ (Y ⊗ Yᘁ) ◁ f ▷ Xᘁ) ⊗≫ Y ◁ ε_ Y Yᘁ ▷ Xᘁ ⊗≫ g ▷ Xᘁ ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = η_ X Xᘁ ⊗≫ f ▷ Xᘁ ⊗≫ (η_ Y Yᘁ ▷ Y ⊗≫ Y ◁ ε_ Y Yᘁ) ▷ Xᘁ ⊗≫ g ▷ Xᘁ ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = η_ X Xᘁ ≫ f ▷ Xᘁ ≫ g ▷ Xᘁ := by - rw [evaluation_coevaluation'']; coherence + rw [evaluation_coevaluation'']; monoidal /-- The composition of left adjoint mates is the adjoint mate of the composition. -/ @[reassoc] @@ -252,14 +252,14 @@ theorem comp_leftAdjointMate {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] [HasLef calc _ = 𝟙 _ ⊗≫ ((𝟙_ C) ◁ η_ (ᘁY) Y ≫ η_ (ᘁX) X ▷ ((ᘁY) ⊗ Y)) ⊗≫ (ᘁX) ◁ f ▷ (ᘁY) ▷ Y ⊗≫ (ᘁX) ◁ ε_ (ᘁY) Y ▷ Y ⊗≫ (ᘁX) ◁ g := by - rw [tensorHom_def]; coherence + rw [tensorHom_def]; monoidal _ = η_ (ᘁX) X ⊗≫ (((ᘁX) ⊗ X) ◁ η_ (ᘁY) Y ≫ ((ᘁX) ◁ f) ▷ ((ᘁY) ⊗ Y)) ⊗≫ (ᘁX) ◁ ε_ (ᘁY) Y ▷ Y ⊗≫ (ᘁX) ◁ g := by - rw [whisker_exchange]; coherence + rw [whisker_exchange]; monoidal _ = η_ (ᘁX) X ⊗≫ ((ᘁX) ◁ f) ⊗≫ (ᘁX) ◁ (Y ◁ η_ (ᘁY) Y ⊗≫ ε_ (ᘁY) Y ▷ Y) ⊗≫ (ᘁX) ◁ g := by - rw [whisker_exchange]; coherence + rw [whisker_exchange]; monoidal _ = η_ (ᘁX) X ≫ (ᘁX) ◁ f ≫ (ᘁX) ◁ g := by - rw [coevaluation_evaluation'']; coherence + rw [coevaluation_evaluation'']; monoidal /-- Given an exact pairing on `Y Y'`, we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)` @@ -276,19 +276,19 @@ def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ left_inv f := by calc _ = 𝟙 _ ⊗≫ Y' ◁ η_ Y Y' ▷ X ⊗≫ ((Y' ⊗ Y) ◁ f ≫ ε_ Y Y' ▷ Z) ⊗≫ 𝟙 _ := by - coherence + monoidal _ = 𝟙 _ ⊗≫ (Y' ◁ η_ Y Y' ⊗≫ ε_ Y Y' ▷ Y') ▷ X ⊗≫ f := by - rw [whisker_exchange]; coherence + rw [whisker_exchange]; monoidal _ = f := by - rw [coevaluation_evaluation'']; coherence + rw [coevaluation_evaluation'']; monoidal right_inv f := by calc _ = 𝟙 _ ⊗≫ (η_ Y Y' ▷ X ≫ (Y ⊗ Y') ◁ f) ⊗≫ Y ◁ ε_ Y Y' ▷ Z ⊗≫ 𝟙 _ := by - coherence + monoidal _ = f ⊗≫ (η_ Y Y' ▷ Y ⊗≫ Y ◁ ε_ Y Y') ▷ Z ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = f := by - rw [evaluation_coevaluation'']; coherence + rw [evaluation_coevaluation'']; monoidal /-- Given an exact pairing on `Y Y'`, we get a bijection on hom-sets `(X ⊗ Y ⟶ Z) ≃ (X ⟶ Z ⊗ Y')` @@ -300,19 +300,19 @@ def tensorRightHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (X ⊗ Y ⟶ Z) ≃ left_inv f := by calc _ = 𝟙 _ ⊗≫ X ◁ η_ Y Y' ▷ Y ⊗≫ (f ▷ (Y' ⊗ Y) ≫ Z ◁ ε_ Y Y') ⊗≫ 𝟙 _ := by - coherence + monoidal _ = 𝟙 _ ⊗≫ X ◁ (η_ Y Y' ▷ Y ⊗≫ Y ◁ ε_ Y Y') ⊗≫ f := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = f := by - rw [evaluation_coevaluation'']; coherence + rw [evaluation_coevaluation'']; monoidal right_inv f := by calc _ = 𝟙 _ ⊗≫ (X ◁ η_ Y Y' ≫ f ▷ (Y ⊗ Y')) ⊗≫ Z ◁ ε_ Y Y' ▷ Y' ⊗≫ 𝟙 _ := by - coherence + monoidal _ = f ⊗≫ Z ◁ (Y' ◁ η_ Y Y' ⊗≫ ε_ Y Y' ▷ Y') ⊗≫ 𝟙 _ := by - rw [whisker_exchange]; coherence + rw [whisker_exchange]; monoidal _ = f := by - rw [coevaluation_evaluation'']; coherence + rw [coevaluation_evaluation'']; monoidal theorem tensorLeftHomEquiv_naturality {X Y Y' Z Z' : C} [ExactPairing Y Y'] (f : Y' ⊗ X ⟶ Z) (g : Z ⟶ Z') : @@ -387,10 +387,10 @@ theorem tensorLeftHomEquiv_symm_coevaluation_comp_whiskerLeft {Y Y' Z : C} [Exac (f : Y' ⟶ Z) : (tensorLeftHomEquiv _ _ _ _).symm (η_ _ _ ≫ Y ◁ f) = (ρ_ _).hom ≫ f := by calc _ = Y' ◁ η_ Y Y' ⊗≫ ((Y' ⊗ Y) ◁ f ≫ ε_ Y Y' ▷ Z) ⊗≫ 𝟙 _ := by - dsimp [tensorLeftHomEquiv]; coherence + dsimp [tensorLeftHomEquiv]; monoidal _ = (Y' ◁ η_ Y Y' ⊗≫ ε_ Y Y' ▷ Y') ⊗≫ f := by - rw [whisker_exchange]; coherence - _ = _ := by rw [coevaluation_evaluation'']; coherence + rw [whisker_exchange]; monoidal + _ = _ := by rw [coevaluation_evaluation'']; monoidal @[simp] theorem tensorLeftHomEquiv_symm_coevaluation_comp_whiskerRight {X Y : C} [HasRightDual X] @@ -411,22 +411,22 @@ theorem tensorRightHomEquiv_symm_coevaluation_comp_whiskerRight {Y Y' Z : C} [Ex (f : Y ⟶ Z) : (tensorRightHomEquiv _ Y _ _).symm (η_ Y Y' ≫ f ▷ Y') = (λ_ _).hom ≫ f := calc _ = η_ Y Y' ▷ Y ⊗≫ (f ▷ (Y' ⊗ Y) ≫ Z ◁ ε_ Y Y') ⊗≫ 𝟙 _ := by - dsimp [tensorRightHomEquiv]; coherence + dsimp [tensorRightHomEquiv]; monoidal _ = (η_ Y Y' ▷ Y ⊗≫ Y ◁ ε_ Y Y') ⊗≫ f := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = _ := by - rw [evaluation_coevaluation'']; coherence + rw [evaluation_coevaluation'']; monoidal @[simp] theorem tensorLeftHomEquiv_whiskerLeft_comp_evaluation {Y Z : C} [HasLeftDual Z] (f : Y ⟶ ᘁZ) : (tensorLeftHomEquiv _ _ _ _) (Z ◁ f ≫ ε_ _ _) = f ≫ (ρ_ _).inv := calc _ = 𝟙 _ ⊗≫ (η_ (ᘁZ : C) Z ▷ Y ≫ ((ᘁZ) ⊗ Z) ◁ f) ⊗≫ (ᘁZ) ◁ ε_ (ᘁZ) Z := by - dsimp [tensorLeftHomEquiv]; coherence + dsimp [tensorLeftHomEquiv]; monoidal _ = f ⊗≫ (η_ (ᘁZ) Z ▷ (ᘁZ) ⊗≫ (ᘁZ) ◁ ε_ (ᘁZ) Z) := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = _ := by - rw [evaluation_coevaluation'']; coherence + rw [evaluation_coevaluation'']; monoidal @[simp] theorem tensorLeftHomEquiv_whiskerRight_comp_evaluation {X Y : C} [HasLeftDual X] [HasLeftDual Y] @@ -445,11 +445,11 @@ theorem tensorRightHomEquiv_whiskerRight_comp_evaluation {X Y : C} [HasRightDual (tensorRightHomEquiv _ _ _ _) (f ▷ X ≫ ε_ X (Xᘁ)) = f ≫ (λ_ _).inv := calc _ = 𝟙 _ ⊗≫ (Y ◁ η_ X Xᘁ ≫ f ▷ (X ⊗ Xᘁ)) ⊗≫ ε_ X Xᘁ ▷ Xᘁ := by - dsimp [tensorRightHomEquiv]; coherence + dsimp [tensorRightHomEquiv]; monoidal _ = f ⊗≫ (Xᘁ ◁ η_ X Xᘁ ⊗≫ ε_ X Xᘁ ▷ Xᘁ) := by - rw [whisker_exchange]; coherence + rw [whisker_exchange]; monoidal _ = _ := by - rw [coevaluation_evaluation'']; coherence + rw [coevaluation_evaluation'']; monoidal -- Next four lemmas passing `fᘁ` or `ᘁf` through (co)evaluations. @[reassoc] @@ -483,28 +483,26 @@ def exactPairingCongrLeft {X X' Y : C} [ExactPairing X' Y] (i : X ≅ X') : Exac evaluation_coevaluation' := calc _ = η_ X' Y ▷ X ⊗≫ (i.inv ▷ (Y ⊗ X) ≫ X ◁ (Y ◁ i.hom)) ⊗≫ X ◁ ε_ X' Y := by - coherence + monoidal _ = 𝟙 _ ⊗≫ (η_ X' Y ▷ X ≫ (X' ⊗ Y) ◁ i.hom) ⊗≫ (i.inv ▷ (Y ⊗ X') ≫ X ◁ ε_ X' Y) ⊗≫ 𝟙 _ := by - rw [← whisker_exchange]; coherence + rw [← whisker_exchange]; monoidal _ = 𝟙 _ ⊗≫ i.hom ⊗≫ (η_ X' Y ▷ X' ⊗≫ X' ◁ ε_ X' Y) ⊗≫ i.inv ⊗≫ 𝟙 _ := by - rw [← whisker_exchange, ← whisker_exchange]; coherence + rw [← whisker_exchange, ← whisker_exchange]; monoidal _ = 𝟙 _ ⊗≫ (i.hom ≫ i.inv) ⊗≫ 𝟙 _ := by - rw [evaluation_coevaluation'']; coherence + rw [evaluation_coevaluation'']; monoidal _ = (λ_ X).hom ≫ (ρ_ X).inv := by rw [Iso.hom_inv_id] - -- coherence failed - simp [monoidalComp] + monoidal coevaluation_evaluation' := by calc _ = Y ◁ η_ X' Y ≫ Y ◁ (i.inv ≫ i.hom) ▷ Y ⊗≫ ε_ X' Y ▷ Y := by - coherence + monoidal _ = Y ◁ η_ X' Y ⊗≫ ε_ X' Y ▷ Y := by - rw [Iso.inv_hom_id]; coherence + rw [Iso.inv_hom_id]; monoidal _ = _ := by rw [coevaluation_evaluation''] - -- coherence failed - simp [monoidalComp] + monoidal /-- Transport an exact pairing across an isomorphism in the second argument. -/ def exactPairingCongrRight {X Y Y' : C} [ExactPairing X Y'] (i : Y ≅ Y') : ExactPairing X Y where @@ -513,28 +511,26 @@ def exactPairingCongrRight {X Y Y' : C} [ExactPairing X Y'] (i : Y ≅ Y') : Exa evaluation_coevaluation' := by calc _ = η_ X Y' ▷ X ⊗≫ X ◁ (i.inv ≫ i.hom) ▷ X ≫ X ◁ ε_ X Y' := by - coherence + monoidal _ = η_ X Y' ▷ X ⊗≫ X ◁ ε_ X Y' := by - rw [Iso.inv_hom_id]; coherence + rw [Iso.inv_hom_id]; monoidal _ = _ := by rw [evaluation_coevaluation''] - -- coherence failed - simp [monoidalComp] + monoidal coevaluation_evaluation' := calc _ = Y ◁ η_ X Y' ⊗≫ (Y ◁ (X ◁ i.inv) ≫ i.hom ▷ (X ⊗ Y)) ⊗≫ ε_ X Y' ▷ Y := by - coherence + monoidal _ = 𝟙 _ ⊗≫ (Y ◁ η_ X Y' ≫ i.hom ▷ (X ⊗ Y')) ⊗≫ ((Y' ⊗ X) ◁ i.inv ≫ ε_ X Y' ▷ Y) ⊗≫ 𝟙 _ := by - rw [whisker_exchange]; coherence + rw [whisker_exchange]; monoidal _ = 𝟙 _ ⊗≫ i.hom ⊗≫ (Y' ◁ η_ X Y' ⊗≫ ε_ X Y' ▷ Y') ⊗≫ i.inv ⊗≫ 𝟙 _ := by - rw [whisker_exchange, whisker_exchange]; coherence + rw [whisker_exchange, whisker_exchange]; monoidal _ = 𝟙 _ ⊗≫ (i.hom ≫ i.inv) ⊗≫ 𝟙 _ := by - rw [coevaluation_evaluation'']; coherence + rw [coevaluation_evaluation'']; monoidal _ = (ρ_ Y).hom ≫ (λ_ Y).inv := by rw [Iso.hom_inv_id] - -- coherence failed - simp [monoidalComp] + monoidal /-- Transport an exact pairing across isomorphisms. -/ def exactPairingCongr {X X' Y Y' : C} [ExactPairing X' Y'] (i : X ≅ X') (j : Y ≅ Y') : diff --git a/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean b/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean index fab3fe97af69a..6e6d9d68e265d 100644 --- a/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean +++ b/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean @@ -25,7 +25,7 @@ private theorem coevaluation_evaluation_braided' [inst : ExactPairing X Y] : /- Whitney trick transcribed: https://mathoverflow.net/a/162729/493261 -/ calc _ = 𝟙 X ⊗≫ X ◁ η_ X Y ⊗≫ (X ◁ (β_ Y X).inv ⊗≫ (β_ X Y).hom ▷ X) ⊗≫ ε_ X Y ▷ X ⊗≫ 𝟙 X := by - coherence + monoidal _ = 𝟙 X ⊗≫ X ◁ η_ X Y ⊗≫ (𝟙 (X ⊗ X ⊗ Y) ⊗≫ (β_ X X).hom ▷ Y ⊗≫ X ◁ (β_ X Y).hom ⊗≫ (β_ Y X).inv ▷ X ⊗≫ Y ◁ (β_ X X).inv ⊗≫ 𝟙 ((Y ⊗ X) ⊗ X)) ⊗≫ ε_ X Y ▷ X ⊗≫ 𝟙 X := by congr 3 @@ -49,7 +49,7 @@ private theorem evaluation_coevaluation_braided' [inst : ExactPairing X Y] : rw [Iso.eq_comp_inv, ← Iso.inv_comp_eq_id] calc _ = 𝟙 Y ⊗≫ η_ X Y ▷ Y ⊗≫ ((β_ Y X).inv ▷ Y ⊗≫ Y ◁ (β_ X Y).hom) ≫ Y ◁ ε_ X Y ⊗≫ 𝟙 Y := by - coherence + monoidal _ = 𝟙 Y ⊗≫ η_ X Y ▷ Y ⊗≫ (𝟙 ((X ⊗ Y) ⊗ Y) ⊗≫ X ◁ (β_ Y Y).hom ⊗≫ (β_ X Y).hom ▷ Y ⊗≫ Y ◁ (β_ Y X).inv ⊗≫ (β_ Y Y).inv ▷ X ⊗≫ 𝟙 (Y ⊗ Y ⊗ X)) ⊗≫ Y ◁ ε_ X Y ⊗≫ 𝟙 Y := by congr 3 diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index 467bdb300b5dc..5b0f01be92910 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -22,10 +22,21 @@ import Mathlib.Tactic.CancelDenoms.Core import Mathlib.Tactic.Cases import Mathlib.Tactic.CasesM import Mathlib.Tactic.CategoryTheory.BicategoricalComp +import Mathlib.Tactic.CategoryTheory.Bicategory.Basic +import Mathlib.Tactic.CategoryTheory.Bicategory.Datatypes +import Mathlib.Tactic.CategoryTheory.Bicategory.Normalize +import Mathlib.Tactic.CategoryTheory.Bicategory.PureCoherence import Mathlib.Tactic.CategoryTheory.BicategoryCoherence import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.Tactic.CategoryTheory.Coherence.Basic +import Mathlib.Tactic.CategoryTheory.Coherence.Datatypes +import Mathlib.Tactic.CategoryTheory.Coherence.Normalize +import Mathlib.Tactic.CategoryTheory.Coherence.PureCoherence import Mathlib.Tactic.CategoryTheory.Elementwise -import Mathlib.Tactic.CategoryTheory.Monoidal +import Mathlib.Tactic.CategoryTheory.Monoidal.Basic +import Mathlib.Tactic.CategoryTheory.Monoidal.Datatypes +import Mathlib.Tactic.CategoryTheory.Monoidal.Normalize +import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence import Mathlib.Tactic.CategoryTheory.MonoidalComp import Mathlib.Tactic.CategoryTheory.Reassoc import Mathlib.Tactic.CategoryTheory.Slice diff --git a/Mathlib/Tactic/CategoryTheory/BicategoricalComp.lean b/Mathlib/Tactic/CategoryTheory/BicategoricalComp.lean index ec242f570e977..a43d5c5ea901b 100644 --- a/Mathlib/Tactic/CategoryTheory/BicategoricalComp.lean +++ b/Mathlib/Tactic/CategoryTheory/BicategoricalComp.lean @@ -26,27 +26,22 @@ Used by the `⊗≫` bicategorical composition operator, and the `coherence` tac -/ class BicategoricalCoherence (f g : a ⟶ b) where /-- The chosen structural isomorphism between to 1-morphisms. -/ - hom : f ⟶ g - [isIso : IsIso hom] + iso : f ≅ g /-- Notation for identities up to unitors and associators. -/ scoped[CategoryTheory.Bicategory] notation " ⊗𝟙 " => - BicategoricalCoherence.hom -- type as \ot 𝟙 - -attribute [instance] BicategoricalCoherence.isIso - -noncomputable section + BicategoricalCoherence.iso -- type as \ot 𝟙 /-- Construct an isomorphism between two objects in a bicategorical category out of unitors and associators. -/ -def bicategoricalIso (f g : a ⟶ b) [BicategoricalCoherence f g] : f ≅ g := - asIso ⊗𝟙 +abbrev bicategoricalIso (f g : a ⟶ b) [BicategoricalCoherence f g] : f ≅ g := + ⊗𝟙 /-- Compose two morphisms in a bicategorical category, inserting unitors and associators between as necessary. -/ def bicategoricalComp {f g h i : a ⟶ b} [BicategoricalCoherence g h] (η : f ⟶ g) (θ : h ⟶ i) : f ⟶ i := - η ≫ ⊗𝟙 ≫ θ + η ≫ ⊗𝟙.hom ≫ θ -- type as \ot \gg @[inherit_doc bicategoricalComp] @@ -56,7 +51,7 @@ scoped[CategoryTheory.Bicategory] infixr:80 " ⊗≫ " => bicategoricalComp inserting unitors and associators between as necessary. -/ def bicategoricalIsoComp {f g h i : a ⟶ b} [BicategoricalCoherence g h] (η : f ≅ g) (θ : h ≅ i) : f ≅ i := - η ≪≫ asIso ⊗𝟙 ≪≫ θ + η ≪≫ ⊗𝟙 ≪≫ θ @[inherit_doc bicategoricalIsoComp] scoped[CategoryTheory.Bicategory] infixr:80 " ≪⊗≫ " => @@ -66,59 +61,59 @@ namespace BicategoricalCoherence @[simps] instance refl (f : a ⟶ b) : BicategoricalCoherence f f := - ⟨𝟙 _⟩ + ⟨Iso.refl _⟩ @[simps] instance whiskerLeft (f : a ⟶ b) (g h : b ⟶ c) [BicategoricalCoherence g h] : BicategoricalCoherence (f ≫ g) (f ≫ h) := - ⟨f ◁ ⊗𝟙⟩ + ⟨whiskerLeftIso f ⊗𝟙⟩ @[simps] instance whiskerRight (f g : a ⟶ b) (h : b ⟶ c) [BicategoricalCoherence f g] : BicategoricalCoherence (f ≫ h) (g ≫ h) := - ⟨⊗𝟙 ▷ h⟩ + ⟨whiskerRightIso ⊗𝟙 h⟩ @[simps] instance tensorRight (f : a ⟶ b) (g : b ⟶ b) [BicategoricalCoherence (𝟙 b) g] : BicategoricalCoherence f (f ≫ g) := - ⟨(ρ_ f).inv ≫ f ◁ ⊗𝟙⟩ + ⟨(ρ_ f).symm ≪≫ (whiskerLeftIso f ⊗𝟙)⟩ @[simps] instance tensorRight' (f : a ⟶ b) (g : b ⟶ b) [BicategoricalCoherence g (𝟙 b)] : BicategoricalCoherence (f ≫ g) f := - ⟨f ◁ ⊗𝟙 ≫ (ρ_ f).hom⟩ + ⟨whiskerLeftIso f ⊗𝟙 ≪≫ (ρ_ f)⟩ @[simps] instance left (f g : a ⟶ b) [BicategoricalCoherence f g] : BicategoricalCoherence (𝟙 a ≫ f) g := - ⟨(λ_ f).hom ≫ ⊗𝟙⟩ + ⟨λ_ f ≪≫ ⊗𝟙⟩ @[simps] instance left' (f g : a ⟶ b) [BicategoricalCoherence f g] : BicategoricalCoherence f (𝟙 a ≫ g) := - ⟨⊗𝟙 ≫ (λ_ g).inv⟩ + ⟨⊗𝟙 ≪≫ (λ_ g).symm⟩ @[simps] instance right (f g : a ⟶ b) [BicategoricalCoherence f g] : BicategoricalCoherence (f ≫ 𝟙 b) g := - ⟨(ρ_ f).hom ≫ ⊗𝟙⟩ + ⟨ρ_ f ≪≫ ⊗𝟙⟩ @[simps] instance right' (f g : a ⟶ b) [BicategoricalCoherence f g] : BicategoricalCoherence f (g ≫ 𝟙 b) := - ⟨⊗𝟙 ≫ (ρ_ g).inv⟩ + ⟨⊗𝟙 ≪≫ (ρ_ g).symm⟩ @[simps] instance assoc (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d) (i : a ⟶ d) [BicategoricalCoherence (f ≫ g ≫ h) i] : BicategoricalCoherence ((f ≫ g) ≫ h) i := - ⟨(α_ f g h).hom ≫ ⊗𝟙⟩ + ⟨α_ f g h ≪≫ ⊗𝟙⟩ @[simps] instance assoc' (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d) (i : a ⟶ d) [BicategoricalCoherence i (f ≫ g ≫ h)] : BicategoricalCoherence i ((f ≫ g) ≫ h) := - ⟨⊗𝟙 ≫ (α_ f g h).inv⟩ + ⟨⊗𝟙 ≪≫ (α_ f g h).symm⟩ end BicategoricalCoherence @@ -126,16 +121,4 @@ end BicategoricalCoherence theorem bicategoricalComp_refl {f g h : a ⟶ b} (η : f ⟶ g) (θ : g ⟶ h) : η ⊗≫ θ = η ≫ θ := by dsimp [bicategoricalComp]; simp -example {f' : a ⟶ d} {f : a ⟶ b} {g : b ⟶ c} {h : c ⟶ d} {h' : a ⟶ d} (η : f' ⟶ f ≫ g ≫ h) - (θ : (f ≫ g) ≫ h ⟶ h') : f' ⟶ h' := - η ⊗≫ θ - --- To automatically insert unitors/associators at the beginning or end, --- you can use `η ⊗≫ 𝟙 _` -example {f' : a ⟶ d} {f : a ⟶ b} {g : b ⟶ c} {h : c ⟶ d} (η : f' ⟶ (f ≫ g) ≫ h) : - f' ⟶ f ≫ g ≫ h := - η ⊗≫ 𝟙 _ - -end - end CategoryTheory diff --git a/Mathlib/Tactic/CategoryTheory/Bicategory/Basic.lean b/Mathlib/Tactic/CategoryTheory/Bicategory/Basic.lean new file mode 100644 index 0000000000000..4a85534c5839e --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Bicategory/Basic.lean @@ -0,0 +1,55 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Basic +import Mathlib.Tactic.CategoryTheory.Bicategory.Normalize +import Mathlib.Tactic.CategoryTheory.Bicategory.PureCoherence + +/-! +# `bicategory` tactic + +This file provides `bicategory` tactic, which solves equations in a bicategory, where +the two sides only differ by replacing strings of bicategory structural morphisms (that is, +associators, unitors, and identities) with different strings of structural morphisms with the same +source and target. In other words, `bicategory` solves equalities where both sides have the same +string diagrams. + +The core function for the `bicategory` tactic is provided in +`Mathlib.Tactic.CategoryTheory.Coherence.Basic`. See this file for more details about the +implementation. + +-/ + +open Lean Meta Elab Tactic +open CategoryTheory Mathlib.Tactic.BicategoryLike + +namespace Mathlib.Tactic.Bicategory + +/-- Normalize the both sides of an equality. -/ +def bicategoryNf (mvarId : MVarId) : MetaM (List MVarId) := do + BicategoryLike.normalForm Bicategory.Context `bicategory mvarId + +@[inherit_doc bicategoryNf] +elab "bicategory_nf" : tactic => withMainContext do + replaceMainGoal (← bicategoryNf (← getMainGoal)) + +/-- +Use the coherence theorem for bicategories to solve equations in a bicategory, +where the two sides only differ by replacing strings of bicategory structural morphisms +(that is, associators, unitors, and identities) +with different strings of structural morphisms with the same source and target. + +That is, `bicategory` can handle goals of the form +`a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c'` +where `a = a'`, `b = b'`, and `c = c'` can be proved using `bicategory_coherence`. +-/ +def bicategory (mvarId : MVarId) : MetaM (List MVarId) := + BicategoryLike.main Bicategory.Context `bicategory mvarId + +@[inherit_doc bicategory] +elab "bicategory" : tactic => withMainContext do + replaceMainGoal <| ← bicategory <| ← getMainGoal + +end Mathlib.Tactic.Bicategory diff --git a/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean b/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean new file mode 100644 index 0000000000000..e7c2dd37d4f41 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean @@ -0,0 +1,511 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Datatypes +import Mathlib.Tactic.CategoryTheory.BicategoricalComp + +/-! +# Expressions for bicategories + +This file converts lean expressions representing 2-morphisms in bicategories into `Mor₂Iso` +or `Mor` terms. The converted expressions are used in the coherence tactics and the string diagram +widgets. + +-/ + +open Lean Meta Elab Qq +open CategoryTheory Mathlib.Tactic.BicategoryLike Bicategory + +namespace Mathlib.Tactic.Bicategory + +/-- The domain of a morphism. -/ +def srcExpr (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Quiver.Hom, #[_, _, f, _]) => return f + | _ => throwError m!"{η} is not a morphism" + +/-- The codomain of a morphism. -/ +def tgtExpr (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Quiver.Hom, #[_, _, _, g]) => return g + | _ => throwError m!"{η} is not a morphism" + +/-- The domain of an isomorphism. -/ +def srcExprOfIso (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Iso, #[_, _, f, _]) => return f + | _ => throwError m!"{η} is not a morphism" + +/-- The codomain of an isomorphism. -/ +def tgtExprOfIso (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Iso, #[_, _, _, g]) => return g + | _ => throwError m!"{η} is not a morphism" + +initialize registerTraceClass `bicategory + +/-- The context for evaluating expressions. -/ +structure Context where + /-- The level for 2-morphisms. -/ + level₂ : Level + /-- The level for 1-morphisms. -/ + level₁ : Level + /-- The level for objects. -/ + level₀ : Level + /-- The expression for the underlying category. -/ + B : Q(Type level₀) + /-- The bicategory instance. -/ + instBicategory : Q(Bicategory.{level₂, level₁} $B) + +/-- Populate a `context` object for evaluating `e`. -/ +def mkContext? (e : Expr) : MetaM (Option Context) := do + let e ← instantiateMVars e + let type ← instantiateMVars <| ← inferType e + match (← whnfR (← inferType e)).getAppFnArgs with + | (``Quiver.Hom, #[_, _, f, _]) => + let fType ← instantiateMVars <| ← inferType f + match (← whnfR fType).getAppFnArgs with + | (``Quiver.Hom, #[_, _, a, _]) => + let B ← inferType a + let .succ level₀ ← getLevel B | return none + let .succ level₁ ← getLevel fType | return none + let .succ level₂ ← getLevel type | return none + let .some instBicategory ← synthInstance? + (mkAppN (.const ``Bicategory [level₂, level₁, level₀]) #[B]) | return none + return some ⟨level₂, level₁, level₀, B, instBicategory⟩ + | _ => return none + | _ => return none + +instance : BicategoryLike.Context Bicategory.Context where + mkContext? := Bicategory.mkContext? + +/-- The monad for the normalization of 2-morphisms. -/ +abbrev BicategoryM := CoherenceM Context + +instance : MonadMor₁ BicategoryM where + id₁M a := do + let ctx ← read + let _bicat := ctx.instBicategory + have a_e : Q($ctx.B) := a.e + return .id q(𝟙 $a_e) a + comp₁M f g := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($b ⟶ $c) := g.e + return .comp q($f_e ≫ $g_e) f g + +section + +universe w v u +variable {B : Type u} [Bicategory.{w, v} B] {a b c d e : B} + +theorem structuralIso_inv {f g : a ⟶ b} (η : f ≅ g) : + η.symm.hom = η.inv := by + simp only [Iso.symm_hom] + +theorem structuralIsoOfExpr_comp {f g h : a ⟶ b} + (η : f ⟶ g) (η' : f ≅ g) (ih_η : η'.hom = η) + (θ : g ⟶ h) (θ' : g ≅ h) (ih_θ : θ'.hom = θ) : + (η' ≪≫ θ').hom = η ≫ θ := by + simp [ih_η, ih_θ] + +theorem structuralIsoOfExpr_whiskerLeft (f : a ⟶ b) {g h : b ⟶ c} + (η : g ⟶ h) (η' : g ≅ h) (ih_η : η'.hom = η) : + (whiskerLeftIso f η').hom = f ◁ η := by + simp [ih_η] + +theorem structuralIsoOfExpr_whiskerRight {f g : a ⟶ b} (h : b ⟶ c) + (η : f ⟶ g) (η' : f ≅ g) (ih_η : η'.hom = η) : + (whiskerRightIso η' h).hom = η ▷ h := by + simp [ih_η] + +theorem StructuralOfExpr_bicategoricalComp {f g h i : a ⟶ b} [BicategoricalCoherence g h] + (η : f ⟶ g) (η' : f ≅ g) (ih_η : η'.hom = η) (θ : h ⟶ i) (θ' : h ≅ i) (ih_θ : θ'.hom = θ) : + (bicategoricalIsoComp η' θ').hom = η ⊗≫ θ := by + simp [ih_η, ih_θ, bicategoricalIsoComp, bicategoricalComp] + +end + +open MonadMor₁ + +instance : MonadMor₂Iso BicategoryM where + associatorM f g h := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have d : Q($ctx.B) := h.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($b ⟶ $c) := g.e + have h_e : Q($c ⟶ $d) := h.e + return .associator q(α_ $f_e $g_e $h_e) f g h + leftUnitorM f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + return .leftUnitor q(λ_ $f_e) f + rightUnitorM f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + return .rightUnitor q(ρ_ $f_e) f + id₂M f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + return .id q(Iso.refl $f_e) f + coherenceHomM f g inst := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have inst : Q(BicategoricalCoherence $f_e $g_e) := inst + match (← whnfI inst).getAppFnArgs with + | (``BicategoricalCoherence.mk, #[_, _, _, _, _, _, α]) => + let e : Q($f_e ≅ $g_e) := q(BicategoricalCoherence.iso) + return ⟨e, f, g, inst, α⟩ + | _ => throwError m!"failed to unfold {inst}" + comp₂M η θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + let h ← θ.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have h_e : Q($a ⟶ $b) := h.e + have η_e : Q($f_e ≅ $g_e) := η.e + have θ_e : Q($g_e ≅ $h_e) := θ.e + return .comp q($η_e ≪≫ $θ_e) f g h η θ + whiskerLeftM f η := do + let ctx ← read + let _bicat := ctx.instBicategory + let g ← η.srcM + let h ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($b ⟶ $c) := g.e + have h_e : Q($b ⟶ $c) := h.e + have η_e : Q($g_e ≅ $h_e) := η.e + return .whiskerLeft q(whiskerLeftIso $f_e $η_e) f g h η + whiskerRightM η h := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := h.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have h_e : Q($b ⟶ $c) := h.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .whiskerRight q(whiskerRightIso $η_e $h_e) f g η h + horizontalCompM _ _ := throwError "horizontal composition is not implemented" + symmM η := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .inv q(Iso.symm $η_e) f g η + coherenceCompM α η θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + let h ← θ.srcM + let i ← θ.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have h_e : Q($a ⟶ $b) := h.e + have i_e : Q($a ⟶ $b) := i.e + have _inst : Q(BicategoricalCoherence $g_e $h_e) := α.inst + have η_e : Q($f_e ≅ $g_e) := η.e + have θ_e : Q($h_e ≅ $i_e) := θ.e + return .coherenceComp q($η_e ≪⊗≫ $θ_e) f g h i α η θ + +open MonadMor₂Iso + +instance : MonadMor₂ BicategoryM where + homM η := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + let e : Q($f_e ⟶ $g_e) := q(Iso.hom $η_e) + have eq : Q(Iso.hom $η_e = $e) := q(rfl) + return .isoHom q(Iso.hom $η_e) ⟨η, eq⟩ η + atomHomM η := do + let ctx ← read + let _bicat := ctx.instBicategory + let f := η.src + let g := η.tgt + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .mk q(Iso.hom $η_e) f g + invM η := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + let e : Q($g_e ⟶ $f_e) := q(Iso.inv $η_e) + let η_inv ← symmM η + let eq : Q(Iso.inv $η_e = $e) := q(Iso.symm_hom $η_e) + return .isoInv e ⟨η_inv, eq⟩ η + atomInvM η := do + let ctx ← read + let _bicat := ctx.instBicategory + let f := η.src + let g := η.tgt + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .mk q(Iso.inv $η_e) g f + id₂M f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + let e : Q($f_e ⟶ $f_e) := q(𝟙 $f_e) + let eq : Q(𝟙 $f_e = $e) := q(Iso.refl_hom $f_e) + return .id e ⟨.structuralAtom <| ← id₂M f, eq⟩ f + comp₂M η θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + let h ← θ.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have h_e : Q($a ⟶ $b) := h.e + have η_e : Q($f_e ⟶ $g_e) := η.e + have θ_e : Q($g_e ⟶ $h_e) := θ.e + let iso_lift? ← (match (η.isoLift?, θ.isoLift?) with + | (some η_iso, some θ_iso) => + have η_iso_e : Q($f_e ≅ $g_e) := η_iso.e.e + have θ_iso_e : Q($g_e ≅ $h_e) := θ_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + have θ_iso_eq : Q(Iso.hom $θ_iso_e = $θ_e) := θ_iso.eq + let eq := q(structuralIsoOfExpr_comp _ _ $η_iso_eq _ _ $θ_iso_eq) + return .some ⟨← comp₂M η_iso.e θ_iso.e, eq⟩ + | _ => return none) + let e : Q($f_e ⟶ $h_e) := q($η_e ≫ $θ_e) + return .comp e iso_lift? f g h η θ + whiskerLeftM f η := do + let ctx ← read + let _bicat := ctx.instBicategory + let g ← η.srcM + let h ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($b ⟶ $c) := g.e + have h_e : Q($b ⟶ $c) := h.e + have η_e : Q($g_e ⟶ $h_e) := η.e + let iso_lift? ← (match η.isoLift? with + | some η_iso => do + have η_iso_e : Q($g_e ≅ $h_e) := η_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + let eq := q(structuralIsoOfExpr_whiskerLeft $f_e _ _ $η_iso_eq) + return .some ⟨← whiskerLeftM f η_iso.e, eq⟩ + | _ => return none) + let e : Q($f_e ≫ $g_e ⟶ $f_e ≫ $h_e) := q($f_e ◁ $η_e) + return .whiskerLeft e iso_lift? f g h η + whiskerRightM η h := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := h.src.e + have c : Q($ctx.B) := h.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have h_e : Q($b ⟶ $c) := h.e + have η_e : Q($f_e ⟶ $g_e) := η.e + let iso_lift? ← (match η.isoLift? with + | some η_iso => do + have η_iso_e : Q($f_e ≅ $g_e) := η_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + let eq := q(structuralIsoOfExpr_whiskerRight $h_e _ _ $η_iso_eq) + return .some ⟨← whiskerRightM η_iso.e h, eq⟩ + | _ => return none) + let e : Q($f_e ≫ $h_e ⟶ $g_e ≫ $h_e) := q($η_e ▷ $h_e) + return .whiskerRight e iso_lift? f g η h + horizontalCompM _ _ := throwError "horizontal composition is not implemented" + coherenceCompM α η θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + let h ← θ.srcM + let i ← θ.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f_e : Q($a ⟶ $b) := f.e + have g_e : Q($a ⟶ $b) := g.e + have h_e : Q($a ⟶ $b) := h.e + have i_e : Q($a ⟶ $b) := i.e + have _inst : Q(BicategoricalCoherence $g_e $h_e) := α.inst + have η_e : Q($f_e ⟶ $g_e) := η.e + have θ_e : Q($h_e ⟶ $i_e) := θ.e + let iso_lift? ← (match (η.isoLift?, θ.isoLift?) with + | (some η_iso, some θ_iso) => do + have η_iso_e : Q($f_e ≅ $g_e) := η_iso.e.e + have θ_iso_e : Q($h_e ≅ $i_e) := θ_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + have θ_iso_eq : Q(Iso.hom $θ_iso_e = $θ_e) := θ_iso.eq + let eq := q(StructuralOfExpr_bicategoricalComp _ _ $η_iso_eq _ _ $θ_iso_eq) + return .some ⟨← coherenceCompM α η_iso.e θ_iso.e, eq⟩ + | _ => return none) + let e : Q($f_e ⟶ $i_e) := q($η_e ⊗≫ $θ_e) + return .coherenceComp e iso_lift? f g h i α η θ + +/-- Check that `e` is definitionally equal to `𝟙 a`. -/ +def id₁? (e : Expr) : BicategoryM (Option Obj) := do + let ctx ← read + let _bicat := ctx.instBicategory + let a : Q($ctx.B) ← mkFreshExprMVar ctx.B + if ← withDefault <| isDefEq e q(𝟙 $a) then + return .some ⟨← instantiateMVars a⟩ + else + return none + +/-- Return `(f, g)` if `e` is definitionally equal to `f ≫ g`. -/ +def comp? (e : Expr) : BicategoryM (Option (Mor₁ × Mor₁)) := do + let ctx ← read + let _bicat := ctx.instBicategory + let a ← mkFreshExprMVarQ ctx.B + let b ← mkFreshExprMVarQ ctx.B + let c ← mkFreshExprMVarQ ctx.B + let f ← mkFreshExprMVarQ q($a ⟶ $b) + let g ← mkFreshExprMVarQ q($b ⟶ $c) + if ← withDefault <| isDefEq e q($f ≫ $g) then + let a ← instantiateMVars a + let b ← instantiateMVars b + let c ← instantiateMVars c + let f ← instantiateMVars f + let g ← instantiateMVars g + return some ((.of ⟨f, ⟨a⟩, ⟨b⟩⟩), .of ⟨g, ⟨b⟩, ⟨c⟩⟩) + else + return none + +/-- Construct a `Mor₁` expression from a Lean expression. -/ +partial def mor₁OfExpr (e : Expr) : BicategoryM Mor₁ := do + if let some f := (← get).cache.find? e then + return f + let f ← + if let some a ← id₁? e then + MonadMor₁.id₁M a + else if let some (f, g) ← comp? e then + MonadMor₁.comp₁M (← mor₁OfExpr f.e) (← mor₁OfExpr g.e) + else + return Mor₁.of ⟨e, ⟨← srcExpr e⟩, ⟨ ← tgtExpr e⟩⟩ + modify fun s => { s with cache := s.cache.insert e f } + return f + +instance : MkMor₁ BicategoryM where + ofExpr := mor₁OfExpr + +/-- Construct a `Mor₂Iso` term from a Lean expression. -/ +partial def Mor₂IsoOfExpr (e : Expr) : BicategoryM Mor₂Iso := do + match (← whnfR e).getAppFnArgs with + | (``Bicategory.associator, #[_, _, _, _, _, _, f, g, h]) => + associatorM' (← MkMor₁.ofExpr f) (← MkMor₁.ofExpr g) (← MkMor₁.ofExpr h) + | (``Bicategory.leftUnitor, #[_, _, _, _, f]) => + leftUnitorM' (← MkMor₁.ofExpr f) + | (``Bicategory.rightUnitor, #[_, _, _, _, f]) => + rightUnitorM' (← MkMor₁.ofExpr f) + | (``Iso.refl, #[_, _, f]) => + id₂M' (← MkMor₁.ofExpr f) + | (``Iso.symm, #[_, _, _, _, η]) => + symmM (← Mor₂IsoOfExpr η) + | (``Iso.trans, #[_, _, _, _, _, η, θ]) => + comp₂M (← Mor₂IsoOfExpr η) (← Mor₂IsoOfExpr θ) + | (``Bicategory.whiskerLeftIso, #[_, _, _, _, _, f, _, _, η]) => + whiskerLeftM (← MkMor₁.ofExpr f) (← Mor₂IsoOfExpr η) + | (``Bicategory.whiskerRightIso, #[_, _, _, _, _, _, _, η, h]) => + whiskerRightM (← Mor₂IsoOfExpr η) (← MkMor₁.ofExpr h) + | (``bicategoricalIsoComp, #[_, _, _, _, _, g, h, _, inst, η, θ]) => + let α ← coherenceHomM (← MkMor₁.ofExpr g) (← MkMor₁.ofExpr h) inst + coherenceCompM α (← Mor₂IsoOfExpr η) (← Mor₂IsoOfExpr θ) + | (``BicategoricalCoherence.iso, #[_, _, _, _, f, g, inst]) => + coherenceHomM' (← MkMor₁.ofExpr f) (← MkMor₁.ofExpr g) inst + | _ => + return .of ⟨e, ← MkMor₁.ofExpr (← srcExprOfIso e), ← MkMor₁.ofExpr (← tgtExprOfIso e)⟩ + +open MonadMor₂ in +/-- Construct a `Mor₂` term from a Lean expression. -/ +partial def Mor₂OfExpr (e : Expr) : BicategoryM Mor₂ := do + match ← whnfR e with + -- whnfR version of `Iso.hom η` + | .proj ``Iso 0 η => homM (← Mor₂IsoOfExpr η) + -- whnfR version of `Iso.inv η` + | .proj ``Iso 1 η => invM (← Mor₂IsoOfExpr η) + | .app .. => match (← whnfR e).getAppFnArgs with + | (``CategoryStruct.id, #[_, _, f]) => id₂M (← MkMor₁.ofExpr f) + | (``CategoryStruct.comp, #[_, _, _, _, _, η, θ]) => + comp₂M (← Mor₂OfExpr η) (← Mor₂OfExpr θ) + | (``Bicategory.whiskerLeft, #[_, _, _, _, _, f, _, _, η]) => + whiskerLeftM (← MkMor₁.ofExpr f) (← Mor₂OfExpr η) + | (``Bicategory.whiskerRight, #[_, _, _, _, _, _, _, η, h]) => + whiskerRightM (← Mor₂OfExpr η) (← MkMor₁.ofExpr h) + | (``bicategoricalComp, #[_, _, _, _, _, g, h, _, inst, η, θ]) => + let α ← coherenceHomM (← MkMor₁.ofExpr g) (← MkMor₁.ofExpr h) inst + coherenceCompM α (← Mor₂OfExpr η) (← Mor₂OfExpr θ) + | _ => return .of ⟨e, ← MkMor₁.ofExpr (← srcExpr e), ← MkMor₁.ofExpr (← tgtExpr e)⟩ + | _ => + return .of ⟨e, ← MkMor₁.ofExpr (← srcExpr e), ← MkMor₁.ofExpr (← tgtExpr e)⟩ + +instance : BicategoryLike.MkMor₂ BicategoryM where + ofExpr := Mor₂OfExpr + +instance : MonadCoherehnceHom BicategoryM where + unfoldM α := Mor₂IsoOfExpr α.unfold + +end Mathlib.Tactic.Bicategory diff --git a/Mathlib/Tactic/CategoryTheory/Bicategory/Normalize.lean b/Mathlib/Tactic/CategoryTheory/Bicategory/Normalize.lean new file mode 100644 index 0000000000000..d53255094d5ee --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Bicategory/Normalize.lean @@ -0,0 +1,548 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Normalize +import Mathlib.Tactic.CategoryTheory.Bicategory.Datatypes + +/-! +# Normalization of 2-morphisms in bicategories + +This file provides the implementation of the normalization given in +`Mathlib.Tactic.CategoryTheory.Coherence.Normalize`. See this file for more details. + +-/ + +open Lean Meta Elab Qq +open CategoryTheory Mathlib.Tactic.BicategoryLike Bicategory + +namespace Mathlib.Tactic.Bicategory + +section + +universe w v u + +variable {B : Type u} [Bicategory.{w, v} B] + +variable {a b c d : B} +variable {f f' g g' h i j : a ⟶ b} + +@[nolint synTaut] +theorem evalComp_nil_nil (α : f ≅ g) (β : g ≅ h) : + (α ≪≫ β).hom = (α ≪≫ β).hom := by + simp + +theorem evalComp_nil_cons (α : f ≅ g) (β : g ≅ h) (η : h ⟶ i) (ηs : i ⟶ j) : + α.hom ≫ (β.hom ≫ η ≫ ηs) = (α ≪≫ β).hom ≫ η ≫ ηs := by + simp + +theorem evalComp_cons (α : f ≅ g) (η : g ⟶ h) {ηs : h ⟶ i} {θ : i ⟶ j} {ι : h ⟶ j} + (e_ι : ηs ≫ θ = ι) : + (α.hom ≫ η ≫ ηs) ≫ θ = α.hom ≫ η ≫ ι := by + simp [e_ι] + +theorem eval_comp + {η η' : f ⟶ g} {θ θ' : g ⟶ h} {ι : f ⟶ h} + (e_η : η = η') (e_θ : θ = θ') (e_ηθ : η' ≫ θ' = ι) : + η ≫ θ = ι := by + simp [e_η, e_θ, e_ηθ] + +theorem eval_of (η : f ⟶ g) : + η = (Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom := by + simp + +theorem eval_monoidalComp + {η η' : f ⟶ g} {α : g ≅ h} {θ θ' : h ⟶ i} {αθ : g ⟶ i} {ηαθ : f ⟶ i} + (e_η : η = η') (e_θ : θ = θ') (e_αθ : α.hom ≫ θ' = αθ) (e_ηαθ : η' ≫ αθ = ηαθ) : + η ≫ α.hom ≫ θ = ηαθ := by + simp [e_η, e_θ, e_αθ, e_ηαθ] + +@[nolint synTaut] +theorem evalWhiskerLeft_nil (f : a ⟶ b) {g h : b ⟶ c} (α : g ≅ h) : + (whiskerLeftIso f α).hom = (whiskerLeftIso f α).hom := by + simp + +theorem evalWhiskerLeft_of_cons + {f : a ⟶ b} {g h i j : b ⟶ c} + (α : g ≅ h) (η : h ⟶ i) {ηs : i ⟶ j} {θ : f ≫ i ⟶ f ≫ j} (e_θ : f ◁ ηs = θ) : + f ◁ (α.hom ≫ η ≫ ηs) = (whiskerLeftIso f α).hom ≫ f ◁ η ≫ θ := by + simp [e_θ] + +theorem evalWhiskerLeft_comp + {f : a ⟶ b} {g : b ⟶ c} {h i : c ⟶ d} + {η : h ⟶ i} {η₁ : g ≫ h ⟶ g ≫ i} {η₂ : f ≫ g ≫ h ⟶ f ≫ g ≫ i} + {η₃ : f ≫ g ≫ h ⟶ (f ≫ g) ≫ i} {η₄ : (f ≫ g) ≫ h ⟶ (f ≫ g) ≫ i} + (e_η₁ : g ◁ η = η₁) (e_η₂ : f ◁ η₁ = η₂) + (e_η₃ : η₂ ≫ (α_ _ _ _).inv = η₃) (e_η₄ : (α_ _ _ _).hom ≫ η₃ = η₄) : + (f ≫ g) ◁ η = η₄ := by + simp [e_η₁, e_η₂, e_η₃, e_η₄] + +theorem evalWhiskerLeft_id {η : f ⟶ g} + {η₁ : f ⟶ 𝟙 a ≫ g} {η₂ : 𝟙 a ≫ f ⟶ 𝟙 a ≫ g} + (e_η₁ : η ≫ (λ_ _).inv = η₁) (e_η₂ : (λ_ _).hom ≫ η₁ = η₂) : + 𝟙 a ◁ η = η₂ := by + simp [e_η₁, e_η₂] + +theorem eval_whiskerLeft + {f : a ⟶ b} {g h : b ⟶ c} + {η η' : g ⟶ h} {θ : f ≫ g ⟶ f ≫ h} + (e_η : η = η') (e_θ : f ◁ η' = θ) : + f ◁ η = θ := by + simp [e_η, e_θ] + +theorem eval_whiskerRight + {f g : a ⟶ b} {h : b ⟶ c} + {η η' : f ⟶ g} {θ : f ≫ h ⟶ g ≫ h} + (e_η : η = η') (e_θ : η' ▷ h = θ) : + η ▷ h = θ := by + simp [e_η, e_θ] + +@[nolint synTaut] +theorem evalWhiskerRight_nil (α : f ≅ g) (h : b ⟶ c) : + α.hom ▷ h = α.hom ▷ h := by + simp + +theorem evalWhiskerRightAux_of {f g : a ⟶ b} (η : f ⟶ g) (h : b ⟶ c) : + η ▷ h = (Iso.refl _).hom ≫ η ▷ h ≫ (Iso.refl _).hom := by + simp + +theorem evalWhiskerRight_cons_of_of + {f g h i : a ⟶ b} {j : b ⟶ c} + {α : f ≅ g} {η : g ⟶ h} {ηs : h ⟶ i} {ηs₁ : h ≫ j ⟶ i ≫ j} + {η₁ : g ≫ j ⟶ h ≫ j} {η₂ : g ≫ j ⟶ i ≫ j} {η₃ : f ≫ j ⟶ i ≫ j} + (e_ηs₁ : ηs ▷ j = ηs₁) (e_η₁ : η ▷ j = η₁) + (e_η₂ : η₁ ≫ ηs₁ = η₂) (e_η₃ : (whiskerRightIso α j).hom ≫ η₂ = η₃) : + (α.hom ≫ η ≫ ηs) ▷ j = η₃ := by + simp_all + +theorem evalWhiskerRight_cons_whisker + {f : a ⟶ b} {g : a ⟶ c} {h i : b ⟶ c} {j : a ⟶ c} {k : c ⟶ d} + {α : g ≅ f ≫ h} {η : h ⟶ i} {ηs : f ≫ i ⟶ j} + {η₁ : h ≫ k ⟶ i ≫ k} {η₂ : f ≫ (h ≫ k) ⟶ f ≫ (i ≫ k)} {ηs₁ : (f ≫ i) ≫ k ⟶ j ≫ k} + {ηs₂ : f ≫ (i ≫ k) ⟶ j ≫ k} {η₃ : f ≫ (h ≫ k) ⟶ j ≫ k} {η₄ : (f ≫ h) ≫ k ⟶ j ≫ k} + {η₅ : g ≫ k ⟶ j ≫ k} + (e_η₁ : ((Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom) ▷ k = η₁) (e_η₂ : f ◁ η₁ = η₂) + (e_ηs₁ : ηs ▷ k = ηs₁) (e_ηs₂ : (α_ _ _ _).inv ≫ ηs₁ = ηs₂) + (e_η₃ : η₂ ≫ ηs₂ = η₃) (e_η₄ : (α_ _ _ _).hom ≫ η₃ = η₄) + (e_η₅ : (whiskerRightIso α k).hom ≫ η₄ = η₅) : + (α.hom ≫ (f ◁ η) ≫ ηs) ▷ k = η₅ := by + simp at e_η₁ e_η₅ + simp [e_η₁, e_η₂, e_ηs₁, e_ηs₂, e_η₃, e_η₄, e_η₅] + +theorem evalWhiskerRight_comp + {f f' : a ⟶ b} {g : b ⟶ c} {h : c ⟶ d} + {η : f ⟶ f'} {η₁ : f ≫ g ⟶ f' ≫ g} {η₂ : (f ≫ g) ≫ h ⟶ (f' ≫ g) ≫ h} + {η₃ : (f ≫ g) ≫ h ⟶ f' ≫ (g ≫ h)} {η₄ : f ≫ (g ≫ h) ⟶ f' ≫ (g ≫ h)} + (e_η₁ : η ▷ g = η₁) (e_η₂ : η₁ ▷ h = η₂) + (e_η₃ : η₂ ≫ (α_ _ _ _).hom = η₃) (e_η₄ : (α_ _ _ _).inv ≫ η₃ = η₄) : + η ▷ (g ≫ h) = η₄ := by + simp [e_η₁, e_η₂, e_η₃, e_η₄] + +theorem evalWhiskerRight_id + {η : f ⟶ g} {η₁ : f ⟶ g ≫ 𝟙 b} {η₂ : f ≫ 𝟙 b ⟶ g ≫ 𝟙 b} + (e_η₁ : η ≫ (ρ_ _).inv = η₁) (e_η₂ : (ρ_ _).hom ≫ η₁ = η₂) : + η ▷ 𝟙 b = η₂ := by + simp [e_η₁, e_η₂] + +theorem eval_bicategoricalComp + {η η' : f ⟶ g} {α : g ≅ h} {θ θ' : h ⟶ i} {αθ : g ⟶ i} {ηαθ : f ⟶ i} + (e_η : η = η') (e_θ : θ = θ') (e_αθ : α.hom ≫ θ' = αθ) (e_ηαθ : η' ≫ αθ = ηαθ) : + η ≫ α.hom ≫ θ = ηαθ := by + simp [e_η, e_θ, e_αθ, e_ηαθ] + +end + +open Mor₂Iso + +instance : MkEvalComp BicategoryM where + mkEvalCompNilNil α β := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← α.srcM + let g ← α.tgtM + let h ← β.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($a ⟶ $b) := h.e + have α : Q($f ≅ $g) := α.e + have β : Q($g ≅ $h) := β.e + return q(evalComp_nil_nil $α $β) + mkEvalCompNilCons α β η ηs := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← α.srcM + let g ← α.tgtM + let h ← β.tgtM + let i ← η.tgtM + let j ← ηs.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($a ⟶ $b) := h.e + have i : Q($a ⟶ $b) := i.e + have j : Q($a ⟶ $b) := j.e + have α : Q($f ≅ $g) := α.e + have β : Q($g ≅ $h) := β.e + have η : Q($h ⟶ $i) := η.e.e + have ηs : Q($i ⟶ $j) := ηs.e.e + return q(evalComp_nil_cons $α $β $η $ηs) + mkEvalCompCons α η ηs θ ι e_ι := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← α.srcM + let g ← α.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + let j ← θ.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($a ⟶ $b) := h.e + have i : Q($a ⟶ $b) := i.e + have j : Q($a ⟶ $b) := j.e + have α : Q($f ≅ $g) := α.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have θ : Q($i ⟶ $j) := θ.e.e + have ι : Q($h ⟶ $j) := ι.e.e + have e_ι : Q($ηs ≫ $θ = $ι) := e_ι + return q(evalComp_cons $α $η $e_ι) + +instance : MkEvalWhiskerLeft BicategoryM where + mkEvalWhiskerLeftNil f α := do + let ctx ← read + let _bicat := ctx.instBicategory + let g ← α.srcM + let h ← α.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($b ⟶ $c) := g.e + have h : Q($b ⟶ $c) := h.e + have α : Q($g ≅ $h) := α.e + return q(evalWhiskerLeft_nil $f $α) + mkEvalWhiskerLeftOfCons f α η ηs θ e_θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let g ← α.srcM + let h ← α.tgtM + let i ← η.tgtM + let j ← ηs.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($b ⟶ $c) := g.e + have h : Q($b ⟶ $c) := h.e + have i : Q($b ⟶ $c) := i.e + have j : Q($b ⟶ $c) := j.e + have α : Q($g ≅ $h) := α.e + have η : Q($h ⟶ $i) := η.e.e + have ηs : Q($i ⟶ $j) := ηs.e.e + have θ : Q($f ≫ $i ⟶ $f ≫ $j) := θ.e.e + have e_θ : Q($f ◁ $ηs = $θ) := e_θ + return q(evalWhiskerLeft_of_cons $α $η $e_θ) + mkEvalWhiskerLeftComp f g η η₁ η₂ η₃ η₄ e_η₁ e_η₂ e_η₃ e_η₄ := do + let ctx ← read + let _bicat := ctx.instBicategory + let h ← η.srcM + let i ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have d : Q($ctx.B) := h.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($b ⟶ $c) := g.e + have h : Q($c ⟶ $d) := h.e + have i : Q($c ⟶ $d) := i.e + have η : Q($h ⟶ $i) := η.e.e + have η₁ : Q($g ≫ $h ⟶ $g ≫ $i) := η₁.e.e + have η₂ : Q($f ≫ $g ≫ $h ⟶ $f ≫ $g ≫ $i) := η₂.e.e + have η₃ : Q($f ≫ $g ≫ $h ⟶ ($f ≫ $g) ≫ $i) := η₃.e.e + have η₄ : Q(($f ≫ $g) ≫ $h ⟶ ($f ≫ $g) ≫ $i) := η₄.e.e + have e_η₁ : Q($g ◁ $η = $η₁) := e_η₁ + have e_η₂ : Q($f ◁ $η₁ = $η₂) := e_η₂ + have e_η₃ : Q($η₂ ≫ (α_ _ _ _).inv = $η₃) := e_η₃ + have e_η₄ : Q((α_ _ _ _).hom ≫ $η₃ = $η₄) := e_η₄ + return q(evalWhiskerLeft_comp $e_η₁ $e_η₂ $e_η₃ $e_η₄) + mkEvalWhiskerLeftId η η₁ η₂ e_η₁ e_η₂ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have η : Q($f ⟶ $g) := η.e.e + have η₁ : Q($f ⟶ 𝟙 $a ≫ $g) := η₁.e.e + have η₂ : Q(𝟙 $a ≫ $f ⟶ 𝟙 $a ≫ $g) := η₂.e.e + have e_η₁ : Q($η ≫ (λ_ _).inv = $η₁) := e_η₁ + have e_η₂ : Q((λ_ _).hom ≫ $η₁ = $η₂) := e_η₂ + return q(evalWhiskerLeft_id $e_η₁ $e_η₂) + +instance : MkEvalWhiskerRight BicategoryM where + mkEvalWhiskerRightAuxOf η h := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := h.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($b ⟶ $c) := h.e + have η : Q($f ⟶ $g) := η.e.e + return q(evalWhiskerRightAux_of $η $h) + mkEvalWhiskerRightAuxCons _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalWhiskerRightNil α h := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← α.srcM + let g ← α.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := h.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($b ⟶ $c) := h.e + have α : Q($f ≅ $g) := α.e + return q(evalWhiskerRight_nil $α $h) + mkEvalWhiskerRightConsOfOf j α η ηs ηs₁ η₁ η₂ η₃ e_ηs₁ e_η₁ e_η₂ e_η₃ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← α.srcM + let g ← α.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := j.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($a ⟶ $b) := h.e + have i : Q($a ⟶ $b) := i.e + have j : Q($b ⟶ $c) := j.e + have α : Q($f ≅ $g) := α.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have ηs₁ : Q($h ≫ $j ⟶ $i ≫ $j) := ηs₁.e.e + have η₁ : Q($g ≫ $j ⟶ $h ≫ $j) := η₁.e.e + have η₂ : Q($g ≫ $j ⟶ $i ≫ $j) := η₂.e.e + have η₃ : Q($f ≫ $j ⟶ $i ≫ $j) := η₃.e.e + have e_ηs₁ : Q($ηs ▷ $j = $ηs₁) := e_ηs₁ + have e_η₁ : Q($η ▷ $j = $η₁) := e_η₁ + have e_η₂ : Q($η₁ ≫ $ηs₁ = $η₂) := e_η₂ + have e_η₃ : Q((whiskerRightIso $α $j).hom ≫ $η₂ = $η₃) := e_η₃ + return q(evalWhiskerRight_cons_of_of $e_ηs₁ $e_η₁ $e_η₂ $e_η₃) + mkEvalWhiskerRightConsWhisker f k α η ηs η₁ η₂ ηs₁ ηs₂ η₃ η₄ η₅ + e_η₁ e_η₂ e_ηs₁ e_ηs₂ e_η₃ e_η₄ e_η₅ := do + let ctx ← read + let _bicat := ctx.instBicategory + let g ← α.srcM + let h ← η.srcM + let i ← η.tgtM + let j ← ηs.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := h.tgt.e + have d : Q($ctx.B) := k.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $c) := g.e + have h : Q($b ⟶ $c) := h.e + have i : Q($b ⟶ $c) := i.e + have j : Q($a ⟶ $c) := j.e + have k : Q($c ⟶ $d) := k.e + have α : Q($g ≅ $f ≫ $h) := α.e + have η : Q($h ⟶ $i) := η.e.e + have ηs : Q($f ≫ $i ⟶ $j) := ηs.e.e + have η₁ : Q($h ≫ $k ⟶ $i ≫ $k) := η₁.e.e + have η₂ : Q($f ≫ ($h ≫ $k) ⟶ $f ≫ ($i ≫ $k)) := η₂.e.e + have ηs₁ : Q(($f ≫ $i) ≫ $k ⟶ $j ≫ $k) := ηs₁.e.e + have ηs₂ : Q($f ≫ ($i ≫ $k) ⟶ $j ≫ $k) := ηs₂.e.e + have η₃ : Q($f ≫ ($h ≫ $k) ⟶ $j ≫ $k) := η₃.e.e + have η₄ : Q(($f ≫ $h) ≫ $k ⟶ $j ≫ $k) := η₄.e.e + have η₅ : Q($g ≫ $k ⟶ $j ≫ $k) := η₅.e.e + have e_η₁ : Q(((Iso.refl _).hom ≫ $η ≫ (Iso.refl _).hom) ▷ $k = $η₁) := e_η₁ + have e_η₂ : Q($f ◁ $η₁ = $η₂) := e_η₂ + have e_ηs₁ : Q($ηs ▷ $k = $ηs₁) := e_ηs₁ + have e_ηs₂ : Q((α_ _ _ _).inv ≫ $ηs₁ = $ηs₂) := e_ηs₂ + have e_η₃ : Q($η₂ ≫ $ηs₂ = $η₃) := e_η₃ + have e_η₄ : Q((α_ _ _ _).hom ≫ $η₃ = $η₄) := e_η₄ + have e_η₅ : Q((whiskerRightIso $α $k).hom ≫ $η₄ = $η₅) := e_η₅ + return q(evalWhiskerRight_cons_whisker $e_η₁ $e_η₂ $e_ηs₁ $e_ηs₂ $e_η₃ $e_η₄ $e_η₅) + mkEvalWhiskerRightComp g h η η₁ η₂ η₃ η₄ e_η₁ e_η₂ e_η₃ e_η₄ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let f' ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have d : Q($ctx.B) := h.tgt.e + have f : Q($a ⟶ $b) := f.e + have f' : Q($a ⟶ $b) := f'.e + have g : Q($b ⟶ $c) := g.e + have h : Q($c ⟶ $d) := h.e + have η : Q($f ⟶ $f') := η.e.e + have η₁ : Q($f ≫ $g ⟶ $f' ≫ $g) := η₁.e.e + have η₂ : Q(($f ≫ $g) ≫ $h ⟶ ($f' ≫ $g) ≫ $h) := η₂.e.e + have η₃ : Q(($f ≫ $g) ≫ $h ⟶ $f' ≫ ($g ≫ $h)) := η₃.e.e + have η₄ : Q($f ≫ ($g ≫ $h) ⟶ $f' ≫ ($g ≫ $h)) := η₄.e.e + have e_η₁ : Q($η ▷ $g = $η₁) := e_η₁ + have e_η₂ : Q($η₁ ▷ $h = $η₂) := e_η₂ + have e_η₃ : Q($η₂ ≫ (α_ _ _ _).hom = $η₃) := e_η₃ + have e_η₄ : Q((α_ _ _ _).inv ≫ $η₃ = $η₄) := e_η₄ + return q(evalWhiskerRight_comp $e_η₁ $e_η₂ $e_η₃ $e_η₄) + mkEvalWhiskerRightId η η₁ η₂ e_η₁ e_η₂ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η.srcM + let g ← η.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have η : Q($f ⟶ $g) := η.e.e + have η₁ : Q($f ⟶ $g ≫ 𝟙 $b) := η₁.e.e + have η₂ : Q($f ≫ 𝟙 $b ⟶ $g ≫ 𝟙 $b) := η₂.e.e + have e_η₁ : Q($η ≫ (ρ_ _).inv = $η₁) := e_η₁ + have e_η₂ : Q((ρ_ _).hom ≫ $η₁ = $η₂) := e_η₂ + return q(evalWhiskerRight_id $e_η₁ $e_η₂) + +instance : MkEvalHorizontalComp BicategoryM where + mkEvalHorizontalCompAuxOf _ _ := do + throwError "not implemented" + mkEvalHorizontalCompAuxCons _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalHorizontalCompAux'Whisker _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalHorizontalCompAux'OfWhisker _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalHorizontalCompNilNil _ _ := do + throwError "not implemented" + mkEvalHorizontalCompNilCons _ _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalHorizontalCompConsNil _ _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalHorizontalCompConsCons _ _ _ _ _ _ _ _ _ _ _ _ _ _ := do + throwError "not implemented" + +instance : MkEval BicategoryM where + mkEvalComp η θ η' θ' ι e_η e_θ e_ηθ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η'.srcM + let g ← η'.tgtM + let h ← θ'.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($a ⟶ $b) := h.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have θ : Q($g ⟶ $h) := θ.e + have θ' : Q($g ⟶ $h) := θ'.e.e + have ι : Q($f ⟶ $h) := ι.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($θ = $θ') := e_θ + have e_ηθ : Q($η' ≫ $θ' = $ι) := e_ηθ + return q(eval_comp $e_η $e_θ $e_ηθ) + mkEvalWhiskerLeft f η η' θ e_η e_θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let g ← η'.srcM + let h ← η'.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := g.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($b ⟶ $c) := g.e + have h : Q($b ⟶ $c) := h.e + have η : Q($g ⟶ $h) := η.e + have η' : Q($g ⟶ $h) := η'.e.e + have θ : Q($f ≫ $g ⟶ $f ≫ $h) := θ.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($f ◁ $η' = $θ) := e_θ + return q(eval_whiskerLeft $e_η $e_θ) + mkEvalWhiskerRight η h η' θ e_η e_θ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η'.srcM + let g ← η'.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have c : Q($ctx.B) := h.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($b ⟶ $c) := h.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have θ : Q($f ≫ $h ⟶ $g ≫ $h) := θ.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($η' ▷ $h = $θ) := e_θ + return q(eval_whiskerRight $e_η $e_θ) + mkEvalHorizontalComp _ _ _ _ _ _ _ _ := do + throwError "not implemented" + mkEvalOf η := do + let ctx ← read + let _bicat := ctx.instBicategory + let f := η.src + let g := η.tgt + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have η : Q($f ⟶ $g) := η.e + return q(eval_of $η) + mkEvalMonoidalComp η θ α η' θ' αθ ηαθ e_η e_θ e_αθ e_ηαθ := do + let ctx ← read + let _bicat := ctx.instBicategory + let f ← η'.srcM + let g ← η'.tgtM + let h ← α.tgtM + let i ← θ'.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have h : Q($a ⟶ $b) := h.e + have i : Q($a ⟶ $b) := i.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have α : Q($g ≅ $h) := α.e + have θ : Q($h ⟶ $i) := θ.e + have θ' : Q($h ⟶ $i) := θ'.e.e + have αθ : Q($g ⟶ $i) := αθ.e.e + have ηαθ : Q($f ⟶ $i) := ηαθ.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($θ = $θ') := e_θ + have e_αθ : Q(Iso.hom $α ≫ $θ' = $αθ) := e_αθ + have e_ηαθ : Q($η' ≫ $αθ = $ηαθ) := e_ηαθ + return q(eval_bicategoricalComp $e_η $e_θ $e_αθ $e_ηαθ) + +instance : MonadNormalExpr BicategoryM where + whiskerRightM η h := do + return .whisker (← MonadMor₂.whiskerRightM η.e (.of h)) η h + hConsM _ _ := do + throwError "not implemented" + whiskerLeftM f η := do + return .whisker (← MonadMor₂.whiskerLeftM (.of f) η.e) f η + nilM α := do + return .nil (← MonadMor₂.homM α) α + consM α η ηs := do + return .cons (← MonadMor₂.comp₂M (← MonadMor₂.homM α) (← MonadMor₂.comp₂M η.e ηs.e)) α η ηs + +instance : MkMor₂ BicategoryM where + ofExpr := Mor₂OfExpr + +end Mathlib.Tactic.Bicategory diff --git a/Mathlib/Tactic/CategoryTheory/Bicategory/PureCoherence.lean b/Mathlib/Tactic/CategoryTheory/Bicategory/PureCoherence.lean new file mode 100644 index 0000000000000..6185cb4adb483 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Bicategory/PureCoherence.lean @@ -0,0 +1,280 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.PureCoherence +import Mathlib.Tactic.CategoryTheory.Bicategory.Datatypes + +/-! +# Coherence tactic for bicategories + +We provide a `bicategory_coherence` tactic, +which proves that any two morphisms (with the same source and target) +in a bicategory which are built out of associators and unitors +are equal. + +-/ + +open Lean Meta Elab Qq +open CategoryTheory Mathlib.Tactic.BicategoryLike Bicategory + +namespace Mathlib.Tactic.Bicategory + +section + +universe w v u + +variable {B : Type u} [Bicategory.{w, v} B] {a b c d e : B} + +local infixr:81 " ◁ " => Bicategory.whiskerLeftIso +local infixl:81 " ▷ " => Bicategory.whiskerRightIso + +/-- The composition of the normalizing isomorphisms `η_f : p ≫ f ≅ pf` and `η_g : pf ≫ g ≅ pfg`. -/ +abbrev normalizeIsoComp {p : a ⟶ b} {f : b ⟶ c} {g : c ⟶ d} {pf : a ⟶ c} {pfg : a ⟶ d} + (η_f : p ≫ f ≅ pf) (η_g : pf ≫ g ≅ pfg) := + (α_ _ _ _).symm ≪≫ whiskerRightIso η_f g ≪≫ η_g + +theorem naturality_associator + {p : a ⟶ b} {f : b ⟶ c} {g : c ⟶ d} {h : d ⟶ e} {pf : a ⟶ c} {pfg : a ⟶ d} {pfgh : a ⟶ e} + (η_f : p ≫ f ≅ pf) (η_g : pf ≫ g ≅ pfg) (η_h : pfg ≫ h ≅ pfgh) : + p ◁ (α_ f g h) ≪≫ (normalizeIsoComp η_f (normalizeIsoComp η_g η_h)) = + (normalizeIsoComp (normalizeIsoComp η_f η_g) η_h) := + Iso.ext (by simp) + +theorem naturality_leftUnitor {p : a ⟶ b} {f : b ⟶ c} {pf : a ⟶ c} (η_f : p ≫ f ≅ pf) : + p ◁ (λ_ f) ≪≫ η_f = normalizeIsoComp (ρ_ p) η_f := + Iso.ext (by simp) + +theorem naturality_rightUnitor {p : a ⟶ b} {f : b ⟶ c} {pf : a ⟶ c} (η_f : p ≫ f ≅ pf) : + p ◁ (ρ_ f) ≪≫ η_f = normalizeIsoComp η_f (ρ_ pf) := + Iso.ext (by simp) + +theorem naturality_id {p : a ⟶ b} {f : b ⟶ c} {pf : a ⟶ c} (η_f : p ≫ f ≅ pf) : + p ◁ Iso.refl f ≪≫ η_f = η_f := + Iso.ext (by simp) + +theorem naturality_comp {p : a ⟶ b} {f g h : b ⟶ c} {pf : a ⟶ c} {η : f ≅ g} {θ : g ≅ h} + (η_f : p ≫ f ≅ pf) (η_g : p ≫ g ≅ pf) (η_h : p ≫ h ≅ pf) + (ih_η : p ◁ η ≪≫ η_g = η_f) (ih_θ : p ◁ θ ≪≫ η_h = η_g) : + p ◁ (η ≪≫ θ) ≪≫ η_h = η_f := by + rw [← ih_η, ← ih_θ] + apply Iso.ext (by simp) + +theorem naturality_whiskerLeft {p : a ⟶ b} {f : b ⟶ c} {g h : c ⟶ d} {pf : a ⟶ c} {pfg : a ⟶ d} + {η : g ≅ h} (η_f : p ≫ f ≅ pf) (η_fg : pf ≫ g ≅ pfg) (η_fh : pf ≫ h ≅ pfg) + (ih_η : pf ◁ η ≪≫ η_fh = η_fg) : + p ◁ (f ◁ η) ≪≫ normalizeIsoComp η_f η_fh = normalizeIsoComp η_f η_fg := by + rw [← ih_η] + apply Iso.ext (by simp [← whisker_exchange_assoc]) + +theorem naturality_whiskerRight {p : a ⟶ b} {f g : b ⟶ c} {h : c ⟶ d} {pf : a ⟶ c} {pfh : a ⟶ d} + {η : f ≅ g} (η_f : p ≫ f ≅ pf) (η_g : p ≫ g ≅ pf) (η_fh : pf ≫ h ≅ pfh) + (ih_η : p ◁ η ≪≫ η_g = η_f) : + p ◁ (η ▷ h) ≪≫ normalizeIsoComp η_g η_fh = normalizeIsoComp η_f η_fh := by + rw [← ih_η] + apply Iso.ext (by simp) + +theorem naturality_inv {p : a ⟶ b} {f g : b ⟶ c} {pf : a ⟶ c} + {η : f ≅ g} (η_f : p ≫ f ≅ pf) (η_g : p ≫ g ≅ pf) (ih : p ◁ η ≪≫ η_g = η_f) : + p ◁ η.symm ≪≫ η_f = η_g := by + rw [← ih] + apply Iso.ext (by simp) + +instance : MonadNormalizeNaturality BicategoryM where + mkNaturalityAssociator p pf pfg pfgh f g h η_f η_g η_h := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have d : Q($ctx.B) := g.tgt.e + have e : Q($ctx.B) := h.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have g : Q($c ⟶ $d) := g.e + have h : Q($d ⟶ $e) := h.e + have pf : Q($a ⟶ $c) := pf.e.e + have pfg : Q($a ⟶ $d) := pfg.e.e + have pfgh : Q($a ⟶ $e) := pfgh.e.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + have η_g : Q($pf ≫ $g ≅ $pfg) := η_g.e + have η_h : Q($pfg ≫ $h ≅ $pfgh) := η_h.e + return q(naturality_associator $η_f $η_g $η_h) + mkNaturalityLeftUnitor p pf f η_f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have pf : Q($a ⟶ $c) := pf.e.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + return q(naturality_leftUnitor $η_f) + mkNaturalityRightUnitor p pf f η_f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have pf : Q($a ⟶ $c) := pf.e.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + return q(naturality_rightUnitor $η_f) + mkNaturalityId p pf f η_f := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have pf : Q($a ⟶ $c) := pf.e.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + return q(naturality_id $η_f) + mkNaturalityComp p pf f g h η θ η_f η_g η_h ih_η ih_θ := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have g : Q($b ⟶ $c) := g.e + have h : Q($b ⟶ $c) := h.e + have pf : Q($a ⟶ $c) := pf.e.e + have η : Q($f ≅ $g) := η.e + have θ : Q($g ≅ $h) := θ.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + have η_g : Q($p ≫ $g ≅ $pf) := η_g.e + have η_h : Q($p ≫ $h ≅ $pf) := η_h.e + have ih_η : Q($p ◁ $η ≪≫ $η_g = $η_f) := ih_η + have ih_θ : Q($p ◁ $θ ≪≫ $η_h = $η_g) := ih_θ + return q(naturality_comp $η_f $η_g $η_h $ih_η $ih_θ) + mkNaturalityWhiskerLeft p pf pfg f g h η η_f η_fg η_fh ih_η := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have d : Q($ctx.B) := g.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have g : Q($c ⟶ $d) := g.e + have h : Q($c ⟶ $d) := h.e + have pf : Q($a ⟶ $c) := pf.e.e + have pfg : Q($a ⟶ $d) := pfg.e.e + have η : Q($g ≅ $h) := η.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + have η_fg : Q($pf ≫ $g ≅ $pfg) := η_fg.e + have η_fh : Q($pf ≫ $h ≅ $pfg) := η_fh.e + have ih_η : Q($pf ◁ $η ≪≫ $η_fh = $η_fg) := ih_η + return q(naturality_whiskerLeft $η_f $η_fg $η_fh $ih_η) + mkNaturalityWhiskerRight p pf pfh f g h η η_f η_g η_fh ih_η := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have d : Q($ctx.B) := h.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have g : Q($b ⟶ $c) := g.e + have h : Q($c ⟶ $d) := h.e + have pf : Q($a ⟶ $c) := pf.e.e + have pfh : Q($a ⟶ $d) := pfh.e.e + have η : Q($f ≅ $g) := η.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + have η_g : Q($p ≫ $g ≅ $pf) := η_g.e + have η_fh : Q($pf ≫ $h ≅ $pfh) := η_fh.e + have ih_η : Q($p ◁ $η ≪≫ $η_g = $η_f) := ih_η + return q(naturality_whiskerRight $η_f $η_g $η_fh $ih_η) + mkNaturalityHorizontalComp _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ := do + throwError "horizontal composition is not implemented" + mkNaturalityInv p pf f g η η_f η_g ih := do + let ctx ← read + let _bicat := ctx.instBicategory + have a : Q($ctx.B) := p.src.e + have b : Q($ctx.B) := p.tgt.e + have c : Q($ctx.B) := f.tgt.e + have p : Q($a ⟶ $b) := p.e.e + have f : Q($b ⟶ $c) := f.e + have g : Q($b ⟶ $c) := g.e + have pf : Q($a ⟶ $c) := pf.e.e + have η : Q($f ≅ $g) := η.e + have η_f : Q($p ≫ $f ≅ $pf) := η_f.e + have η_g : Q($p ≫ $g ≅ $pf) := η_g.e + have ih : Q($p ◁ $η ≪≫ $η_g = $η_f) := ih + return q(naturality_inv $η_f $η_g $ih) + +theorem of_normalize_eq {f g f' : a ⟶ b} {η θ : f ≅ g} (η_f : 𝟙 a ≫ f ≅ f') (η_g : 𝟙 a ≫ g ≅ f') + (h_η : 𝟙 a ◁ η ≪≫ η_g = η_f) + (h_θ : 𝟙 a ◁ θ ≪≫ η_g = η_f) : η = θ := by + apply Iso.ext + calc + η.hom = (λ_ f).inv ≫ η_f.hom ≫ η_g.inv ≫ (λ_ g).hom := by + simp [← reassoc_of% (congrArg Iso.hom h_η)] + _ = θ.hom := by + simp [← reassoc_of% (congrArg Iso.hom h_θ)] + +theorem mk_eq_of_naturality {f g f' : a ⟶ b} {η θ : f ⟶ g} {η' θ' : f ≅ g} + (η_f : 𝟙 a ≫ f ≅ f') (η_g : 𝟙 a ≫ g ≅ f') + (Hη : η'.hom = η) (Hθ : θ'.hom = θ) + (Hη' : whiskerLeftIso (𝟙 a) η' ≪≫ η_g = η_f) + (Hθ' : whiskerLeftIso (𝟙 a) θ' ≪≫ η_g = η_f) : η = θ := + calc + η = η'.hom := Hη.symm + _ = (λ_ f).inv ≫ η_f.hom ≫ η_g.inv ≫ (λ_ g).hom := by + simp [← reassoc_of% (congrArg Iso.hom Hη')] + _ = θ'.hom := by + simp [← reassoc_of% (congrArg Iso.hom Hθ')] + _ = θ := Hθ + +end + +instance : MkEqOfNaturality BicategoryM where + mkEqOfNaturality η θ ηIso θIso η_f η_g Hη Hθ := do + let ctx ← read + let _bicat := ctx.instBicategory + let η' := ηIso.e + let θ' := θIso.e + let f ← η'.srcM + let g ← η'.tgtM + let f' ← η_f.tgtM + have a : Q($ctx.B) := f.src.e + have b : Q($ctx.B) := f.tgt.e + have f : Q($a ⟶ $b) := f.e + have g : Q($a ⟶ $b) := g.e + have f' : Q($a ⟶ $b) := f'.e + have η : Q($f ⟶ $g) := η + have θ : Q($f ⟶ $g) := θ + have η'_e : Q($f ≅ $g) := η'.e + have θ'_e : Q($f ≅ $g) := θ'.e + have η_f : Q(𝟙 $a ≫ $f ≅ $f') := η_f.e + have η_g : Q(𝟙 $a ≫ $g ≅ $f') := η_g.e + have η_hom : Q(Iso.hom $η'_e = $η) := ηIso.eq + have Θ_hom : Q(Iso.hom $θ'_e = $θ) := θIso.eq + have Hη : Q(whiskerLeftIso (𝟙 $a) $η'_e ≪≫ $η_g = $η_f) := Hη + have Hθ : Q(whiskerLeftIso (𝟙 $a) $θ'_e ≪≫ $η_g = $η_f) := Hθ + return q(mk_eq_of_naturality $η_f $η_g $η_hom $Θ_hom $Hη $Hθ) + +open Elab.Tactic + +/-- Close the goal of the form `η = θ`, where `η` and `θ` are 2-isomorphisms made up only of +associators, unitors, and identities. +```lean +example {B : Type} [Bicategory B] {a : B} : + (λ_ (𝟙 a)).hom = (ρ_ (𝟙 a)).hom := by + bicategory_coherence +``` +-/ +def pureCoherence (mvarId : MVarId) : MetaM (List MVarId) := + BicategoryLike.pureCoherence Bicategory.Context `bicategory mvarId + +@[inherit_doc pureCoherence] +elab "bicategory_coherence" : tactic => withMainContext do + replaceMainGoal <| ← Bicategory.pureCoherence <| ← getMainGoal + +end Mathlib.Tactic.Bicategory diff --git a/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean b/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean index 3973e6312e46f..2e58492c79e90 100644 --- a/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean +++ b/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean @@ -112,8 +112,10 @@ def mkLiftMap₂LiftExpr (e : Expr) : TermElabM Expr := do def bicategory_coherence (g : MVarId) : TermElabM Unit := g.withContext do withOptions (fun opts => synthInstance.maxSize.set opts (max 256 (synthInstance.maxSize.get opts))) do - let (ty, _) ← dsimp (← g.getType) - { simpTheorems := #[.addDeclToUnfoldCore {} ``BicategoricalCoherence.hom] } + let thms := [``BicategoricalCoherence.iso, ``Iso.trans, ``Iso.symm, ``Iso.refl, + ``Bicategory.whiskerRightIso, ``Bicategory.whiskerLeftIso].foldl + (·.addDeclToUnfoldCore ·) {} + let (ty, _) ← dsimp (← g.getType) { simpTheorems := #[thms] } let some (_, lhs, rhs) := (← whnfR ty).eq? | exception g "Not an equation of morphisms." let lift_lhs ← mkLiftMap₂LiftExpr lhs let lift_rhs ← mkLiftMap₂LiftExpr rhs diff --git a/Mathlib/Tactic/CategoryTheory/Coherence.lean b/Mathlib/Tactic/CategoryTheory/Coherence.lean index 2cb4c5819fd89..796dc395f7e3c 100644 --- a/Mathlib/Tactic/CategoryTheory/Coherence.lean +++ b/Mathlib/Tactic/CategoryTheory/Coherence.lean @@ -186,9 +186,10 @@ elab (name := liftable_prefixes) "liftable_prefixes" : tactic => do (max 256 (synthInstance.maxSize.get opts))) do evalTactic (← `(tactic| (simp (config := {failIfUnchanged := false}) only - [monoidalComp, Category.assoc, BicategoricalCoherence.hom, + [monoidalComp, bicategoricalComp, Category.assoc, BicategoricalCoherence.iso, MonoidalCoherence.iso, Iso.trans, Iso.symm, Iso.refl, - MonoidalCategory.whiskerRightIso, MonoidalCategory.whiskerLeftIso]) <;> + MonoidalCategory.whiskerRightIso, MonoidalCategory.whiskerLeftIso, + Bicategory.whiskerRightIso, Bicategory.whiskerLeftIso]) <;> (apply (cancel_epi (𝟙 _)).1 <;> try infer_instance) <;> (simp (config := {failIfUnchanged := false}) only [assoc_liftHom, Mathlib.Tactic.BicategoryCoherence.assoc_liftHom₂]))) diff --git a/Mathlib/Tactic/CategoryTheory/Coherence/Basic.lean b/Mathlib/Tactic/CategoryTheory/Coherence/Basic.lean new file mode 100644 index 0000000000000..53facfd616c82 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Coherence/Basic.lean @@ -0,0 +1,107 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Normalize +import Mathlib.Tactic.CategoryTheory.Coherence.PureCoherence +import Mathlib.CategoryTheory.Category.Basic + +/-! +# The Core function for `monoidal` and `bicategory` tactics + +This file provides the function `BicategoryLike.main` for proving equalities in monoidal categories +and bicategories. Using `main`, we will define the following tactics: +- `monoidal` at `Mathlib.Tactic.CategoryTheory.Monoidal.Basic` +- `bicategory` at `Mathlib.Tactic.CategoryTheory.Bicategory.Basic` + +The `main` first normalizes the both sides using `eval`, then compares the corresponding components. +It closes the goal at non-structural parts with `rfl` and the goal at structural parts by +`pureCoherence`. + +-/ + +open Lean Meta Elab +open CategoryTheory Mathlib.Tactic.BicategoryLike + +namespace Mathlib.Tactic.BicategoryLike + +theorem mk_eq {α : Type _} (a b a' b' : α) (ha : a = a') (hb : b = b') (h : a' = b') : a = b := by + simp [h, ha, hb] + +/-- Transform an equality between 2-morphisms into the equality between their normalizations. -/ +def normalForm (ρ : Type) [Context ρ] + [MonadMor₁ (CoherenceM ρ)] + [MonadMor₂Iso (CoherenceM ρ)] + [MonadNormalExpr (CoherenceM ρ)] [MkEval (CoherenceM ρ)] + [MkMor₂ (CoherenceM ρ)] + [MonadMor₂ (CoherenceM ρ)] + (nm : Name) (mvarId : MVarId) : MetaM (List MVarId) := do + mvarId.withContext do + let e ← instantiateMVars <| ← mvarId.getType + withTraceNode nm (fun _ => return m!"normalize: {e}") do + let some (_, e₁, e₂) := (← whnfR <| ← instantiateMVars <| e).eq? + | throwError "{nm}_nf requires an equality goal" + let ctx : ρ ← mkContext e₁ + CoherenceM.run (ctx := ctx) do + let e₁' ← MkMor₂.ofExpr e₁ + let e₂' ← MkMor₂.ofExpr e₂ + let e₁'' ← eval nm e₁' + let e₂'' ← eval nm e₂' + let H ← mkAppM ``mk_eq #[e₁, e₂, e₁''.expr.e.e, e₂''.expr.e.e, e₁''.proof, e₂''.proof] + mvarId.apply H + +universe v u + +theorem mk_eq_of_cons {C : Type u} [CategoryStruct.{v} C] + {f₁ f₂ f₃ f₄ : C} + (α α' : f₁ ⟶ f₂) (η η' : f₂ ⟶ f₃) (ηs ηs' : f₃ ⟶ f₄) + (e_α : α = α') (e_η : η = η') (e_ηs : ηs = ηs') : + α ≫ η ≫ ηs = α' ≫ η' ≫ ηs' := by + simp [e_α, e_η, e_ηs] + +/-- Split the goal `α ≫ η ≫ ηs = α' ≫ η' ≫ ηs'` into `α = α'`, `η = η'`, and `ηs = ηs'`. -/ +def ofNormalizedEq (mvarId : MVarId) : MetaM (List MVarId) := do + mvarId.withContext do + let e ← instantiateMVars <| ← mvarId.getType + let some (_, e₁, e₂) := (← whnfR e).eq? | throwError "requires an equality goal" + match (← whnfR e₁).getAppFnArgs, (← whnfR e₂).getAppFnArgs with + | (``CategoryStruct.comp, #[_, _, _, _, _, α, η]) , + (``CategoryStruct.comp, #[_, _, _, _, _, α', η']) => + match (← whnfR η).getAppFnArgs, (← whnfR η').getAppFnArgs with + | (``CategoryStruct.comp, #[_, _, _, _, _, η, ηs]), + (``CategoryStruct.comp, #[_, _, _, _, _, η', ηs']) => + let e_α ← mkFreshExprMVar (← Meta.mkEq α α') + let e_η ← mkFreshExprMVar (← Meta.mkEq η η') + let e_ηs ← mkFreshExprMVar (← Meta.mkEq ηs ηs') + let x ← mvarId.apply (← mkAppM ``mk_eq_of_cons #[α, α', η, η', ηs, ηs', e_α, e_η, e_ηs]) + return x + | _, _ => throwError "failed to make a normalized equality for {e}" + | _, _ => throwError "failed to make a normalized equality for {e}" + +/-- List.splitEvenOdd [0, 1, 2, 3, 4] = ([0, 2, 4], [1, 3]) -/ +def List.splitEvenOdd {α : Type u} : List α → List α × List α + | [] => ([], []) + | [a] => ([a], []) + | a::b::xs => + let (as, bs) := List.splitEvenOdd xs + (a::as, b::bs) + +/-- The core function for `monoidal` and `bicategory` tactics. -/ +def main (ρ : Type) [Context ρ] [MonadMor₁ (CoherenceM ρ)] [MonadMor₂Iso (CoherenceM ρ)] + [MonadNormalExpr (CoherenceM ρ)] [MkEval (CoherenceM ρ)] [MkMor₂ (CoherenceM ρ)] + [MonadMor₂ (CoherenceM ρ)] [MonadCoherehnceHom (CoherenceM ρ)] + [MonadNormalizeNaturality (CoherenceM ρ)] [MkEqOfNaturality (CoherenceM ρ)] + (nm : Name) (mvarId : MVarId) : MetaM (List MVarId) := + mvarId.withContext do + let mvarIds ← normalForm ρ nm mvarId + let (mvarIdsCoherence, mvarIdsRefl) := List.splitEvenOdd (← repeat' ofNormalizedEq mvarIds) + for mvarId in mvarIdsRefl do mvarId.refl + let mvarIds'' ← mvarIdsCoherence.mapM fun mvarId => do + withTraceNode nm (fun _ => do return m!"goal: {← mvarId.getType}") do + try + pureCoherence ρ nm mvarId + catch _ => return [mvarId] + return mvarIds''.join + +end Mathlib.Tactic.BicategoryLike diff --git a/Mathlib/Tactic/CategoryTheory/Coherence/Datatypes.lean b/Mathlib/Tactic/CategoryTheory/Coherence/Datatypes.lean new file mode 100644 index 0000000000000..52e90c1260e65 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Coherence/Datatypes.lean @@ -0,0 +1,467 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Lean + +/-! +# Datatypes for bicategory like structures + +This file defines the basic datatypes for bicategory like structures. We will use these datatypes +to write tactics that can be applied to both monoidal categories and bicategories: +- `Obj`: objects type +- `Atom₁`: atomic 1-morphisms type +- `Mor₁`: 1-morphisms type +- `Atom`: atomic non-structural 2-morphisms type +- `Mor₂`: 2-morphisms type +- `AtomIso`: atomic non-structural 2-isomorphisms type +- `Mor₂Iso`: 2-isomorphisms type +- `NormalizedHom`: normalized 1-morphisms type + +A term of these datatypes wraps the corresponding `Expr` term, which can be extracted by +e.g. `η.e` for `η : Mor₂`. + +The operations of these datatypes are defined in a monad `m` with the corresponding typeclasses: +- `MonadMor₁`: operations on `Mor₁` +- `MonadMor₂Iso`: operations on `Mor₂Iso` +- `MonadMor₂`: operations on `Mor₂` + +For example, a monad `m` with `[MonadMor₂ m]` provides the operation +`MonadMor₂.comp₂M : Mor₂Iso → Mor₂Iso → m Mor₂Iso`, which constructs the expression for the +composition `η ≫ θ` of 2-morphisms `η` and `θ` in the monad `m`. + +-/ + +open Lean Meta + +namespace Mathlib.Tactic + +namespace BicategoryLike + +/-- Expressions for objects. -/ +structure Obj where + /-- Extracts a lean expression from an `Obj` term. Return `none` in the monoidal + category context. -/ + e? : Option Expr + deriving Inhabited + +/-- Extract a lean expression from an `Obj` term. -/ +def Obj.e (a : Obj) : Expr := + a.e?.get! + +/-- Expressions for atomic 1-morphisms. -/ +structure Atom₁ : Type where + /-- Extract a lean expression from an `Atom₁` term. -/ + e : Expr + /-- The domain of the 1-morphism. -/ + src : Obj + /-- The codomain of the 1-morphism. -/ + tgt : Obj + deriving Inhabited + +/-- A monad equipped with the ability to construct `Atom₁` terms. -/ +class MkAtom₁ (m : Type → Type) where + /-- Construct a `Atom₁` term from a lean expression. -/ + ofExpr (e : Expr) : m Atom₁ + +/-- Expressions for 1-morphisms. -/ +inductive Mor₁ : Type + /-- `id e a` is the expression for `𝟙 a`, where `e` is the underlying lean expression. -/ + | id (e : Expr) (a : Obj) : Mor₁ + /-- `comp e f g` is the expression for `f ≫ g`, where `e` is the underlying lean expression. -/ + | comp (e : Expr) : Mor₁ → Mor₁ → Mor₁ + /-- The expression for an atomic 1-morphism. -/ + | of : Atom₁ → Mor₁ + deriving Inhabited + +/-- A monad equipped with the ability to construct `Mor₁` terms. -/ +class MkMor₁ (m : Type → Type) where + /-- Construct a `Mor₁` term from a lean expression. -/ + ofExpr (e : Expr) : m Mor₁ + +/-- The underlying lean expression of a 1-morphism. -/ +def Mor₁.e : Mor₁ → Expr + | .id e _ => e + | .comp e _ _ => e + | .of a => a.e + +/-- The domain of a 1-morphism. -/ +def Mor₁.src : Mor₁ → Obj + | .id _ a => a + | .comp _ f _ => f.src + | .of f => f.src + +/-- The codomain of a 1-morphism. -/ +def Mor₁.tgt : Mor₁ → Obj + | .id _ a => a + | .comp _ _ g => g.tgt + | .of f => f.tgt + +/-- Converts a 1-morphism into a list of its components. -/ +def Mor₁.toList : Mor₁ → List Atom₁ + | .id _ _ => [] + | .comp _ f g => f.toList ++ g.toList + | .of f => [f] + +/-- A monad equipped with the ability to manipulate 1-morphisms. -/ +class MonadMor₁ (m : Type → Type) where + /-- The expression for `𝟙 a`. -/ + id₁M (a : Obj) : m Mor₁ + /-- The expression for `f ≫ g`. -/ + comp₁M (f g : Mor₁) : m Mor₁ + +/-- Expressions for coherence isomorphisms (i.e., structural 2-morphisms +giveb by `BicategorycalCoherence.iso`). -/ +structure CoherenceHom where + /-- The underlying lean expression of a coherence isomorphism. -/ + e : Expr + /-- The domain of a coherence isomorphism. -/ + src : Mor₁ + /-- The codomain of a coherence isomorphism. -/ + tgt : Mor₁ + /-- The `BicategoricalCoherence` instance. -/ + inst : Expr + /-- Extract the structural 2-isomorphism. -/ + unfold : Expr + deriving Inhabited + +/-- Expressions for atomic non-structural 2-isomorphisms. -/ +structure AtomIso where + /-- The underlying lean expression of an `AtomIso` term. -/ + e : Expr + /-- The domain of a 2-isomorphism. -/ + src : Mor₁ + /-- The codomain of a 2-isomorphism. -/ + tgt : Mor₁ + deriving Inhabited + +/-- Expressions for atomic structural 2-morphisms. -/ +inductive StructuralAtom : Type + /-- The expression for the associator `α_ f g h`. -/ + | associator (e : Expr) (f g h : Mor₁) : StructuralAtom + /-- The expression for the left unitor `λ_ f`. -/ + | leftUnitor (e : Expr) (f : Mor₁) : StructuralAtom + /-- The expression for the right unitor `ρ_ f`. -/ + | rightUnitor (e : Expr) (f : Mor₁) : StructuralAtom + | id (e : Expr) (f : Mor₁) : StructuralAtom + | coherenceHom (α : CoherenceHom) : StructuralAtom + deriving Inhabited + +/-- Expressions for 2-isomorphisms. -/ +inductive Mor₂Iso : Type where + | structuralAtom (α : StructuralAtom) : Mor₂Iso + | comp (e : Expr) (f g h : Mor₁) (η θ : Mor₂Iso) : Mor₂Iso + | whiskerLeft (e : Expr) (f g h : Mor₁) (η : Mor₂Iso) : Mor₂Iso + | whiskerRight (e : Expr) (f g : Mor₁) (η : Mor₂Iso) (h : Mor₁) : Mor₂Iso + | horizontalComp (e : Expr) (f₁ g₁ f₂ g₂ : Mor₁) (η θ : Mor₂Iso) : Mor₂Iso + | inv (e : Expr) (f g : Mor₁) (η : Mor₂Iso) : Mor₂Iso + | coherenceComp (e : Expr) (f g h i : Mor₁) (α : CoherenceHom) (η θ : Mor₂Iso) : Mor₂Iso + | of (η : AtomIso) : Mor₂Iso + deriving Inhabited + +/-- A monad equipped with the ability to unfold `BicategoricalCoherence.iso`. -/ +class MonadCoherehnceHom (m : Type → Type) where + /-- Unfold a coherence isomorphism. -/ + unfoldM (α : CoherenceHom) : m Mor₂Iso + +/-- The underlying lean expression of a 2-isomorphism. -/ +def StructuralAtom.e : StructuralAtom → Expr + | .associator e .. => e + | .leftUnitor e .. => e + | .rightUnitor e .. => e + | .id e .. => e + | .coherenceHom α => α.e + +open MonadMor₁ + +variable {m : Type → Type} [Monad m] + +/-- The domain of a 2-isomorphism. -/ +def StructuralAtom.srcM [MonadMor₁ m] : StructuralAtom → m Mor₁ + | .associator _ f g h => do comp₁M (← comp₁M f g) h + | .leftUnitor _ f => do comp₁M (← id₁M f.src) f + | .rightUnitor _ f => do comp₁M f (← id₁M f.tgt) + | .id _ f => return f + | .coherenceHom α => return α.src + +/-- The codomain of a 2-isomorphism. -/ +def StructuralAtom.tgtM [MonadMor₁ m] : StructuralAtom → m Mor₁ + | .associator _ f g h => do comp₁M f (← comp₁M g h) + | .leftUnitor _ f => return f + | .rightUnitor _ f => return f + | .id _ f => return f + | .coherenceHom α => return α.tgt + +/-- The underlying lean expression of a 2-isomorphism. -/ +def Mor₂Iso.e : Mor₂Iso → Expr + | .structuralAtom α => α.e + | .comp e .. => e + | .whiskerLeft e .. => e + | .whiskerRight e .. => e + | .horizontalComp e .. => e + | .inv e .. => e + | .coherenceComp e .. => e + | .of η => η.e + +/-- The domain of a 2-isomorphism. -/ +def Mor₂Iso.srcM {m : Type → Type} [Monad m] [MonadMor₁ m] : Mor₂Iso → m Mor₁ + | .structuralAtom α => α.srcM + | .comp _ f .. => return f + | .whiskerLeft _ f g .. => do comp₁M f g + | .whiskerRight _ f _ _ h => do comp₁M f h + | .horizontalComp _ f₁ _ f₂ .. => do comp₁M f₁ f₂ + | .inv _ _ g _ => return g + | .coherenceComp _ f .. => return f + | .of η => return η.src + +/-- The codomain of a 2-isomorphism. -/ +def Mor₂Iso.tgtM {m : Type → Type} [Monad m] [MonadMor₁ m] : Mor₂Iso → m Mor₁ + | .structuralAtom α => α.tgtM + | .comp _ _ _ h .. => return h + | .whiskerLeft _ f _ h _ => do comp₁M f h + | .whiskerRight _ _ g _ h => do comp₁M g h + | .horizontalComp _ _ g₁ _ g₂ _ _ => do comp₁M g₁ g₂ + | .inv _ f _ _ => return f + | .coherenceComp _ _ _ _ i .. => return i + | .of η => return η.tgt + +/-- A monad equipped with the ability to construct `Mor₂Iso` terms. -/ +class MonadMor₂Iso (m : Type → Type) where + /-- The expression for the associator `α_ f g h`. -/ + associatorM (f g h : Mor₁) : m StructuralAtom + /-- The expression for the left unitor `λ_ f`. -/ + leftUnitorM (f : Mor₁) : m StructuralAtom + /-- The expression for the right unitor `ρ_ f`. -/ + rightUnitorM (f : Mor₁) : m StructuralAtom + /-- The expression for the identity `Iso.refl f`. -/ + id₂M (f : Mor₁) : m StructuralAtom + /-- The expression for the coherence isomorphism `⊗𝟙 : f ⟶ g`. -/ + coherenceHomM (f g : Mor₁) (inst : Expr) : m CoherenceHom + /-- The expression for the composition `η ≪≫ θ`. -/ + comp₂M (η θ : Mor₂Iso) : m Mor₂Iso + /-- The expression for the left whiskering `whiskerLeftIso f η`. -/ + whiskerLeftM (f : Mor₁) (η : Mor₂Iso) : m Mor₂Iso + /-- The expression for the right whiskering `whiskerRightIso η h`. -/ + whiskerRightM (η : Mor₂Iso) (h : Mor₁) : m Mor₂Iso + /-- The expression for the horizontal composition `η ◫ θ`. -/ + horizontalCompM (η θ : Mor₂Iso) : m Mor₂Iso + /-- The expression for the inverse `Iso.symm η`. -/ + symmM (η : Mor₂Iso) : m Mor₂Iso + /-- The expression for the coherence composition `η ≪⊗≫ θ := η ≪≫ α ≪≫ θ`. -/ + coherenceCompM (α : CoherenceHom) (η θ : Mor₂Iso) : m Mor₂Iso + +namespace MonadMor₂Iso + +variable {m : Type → Type} [Monad m] [MonadMor₂Iso m] + +/-- The expression for the associator `α_ f g h`. -/ +def associatorM' (f g h : Mor₁) : m Mor₂Iso := do + return .structuralAtom <| ← MonadMor₂Iso.associatorM f g h + +/-- The expression for the left unitor `λ_ f`. -/ +def leftUnitorM' (f : Mor₁) : m Mor₂Iso := do + return .structuralAtom <| ← MonadMor₂Iso.leftUnitorM f + +/-- The expression for the right unitor `ρ_ f`. -/ +def rightUnitorM' (f : Mor₁) : m Mor₂Iso := do + return .structuralAtom <| ← MonadMor₂Iso.rightUnitorM f + +/-- The expression for the identity `Iso.refl f`. -/ +def id₂M' (f : Mor₁) : m Mor₂Iso := do + return .structuralAtom <| ← MonadMor₂Iso.id₂M f + +/-- The expression for the coherence isomorphism `⊗𝟙 : f ⟶ g`. -/ +def coherenceHomM' (f g : Mor₁) (inst : Expr) : m Mor₂Iso := do + return .structuralAtom <| .coherenceHom <| ← MonadMor₂Iso.coherenceHomM f g inst + +end MonadMor₂Iso + +/-- Expressions for atomic non-structural 2-morphisms. -/ +structure Atom where + /-- Extract a lean expression from an `Atom` expression. -/ + e : Expr + /-- The domain of a 2-morphism. -/ + src : Mor₁ + /-- The codomain of a 2-morphism. -/ + tgt : Mor₁ + deriving Inhabited + +/-- `Mor₂` expressions defined below will have the `isoLift? : Option IsoLift` field. +For `η : Mor₂` such that `η.isoLift? = .some isoLift`, we have the following data: +- `isoLift.e`: an expression for a 2-isomorphism `η'`, given as a `Mor₂Iso` term, +- `isoLift.eq`: a lean expression for the proof that `η'.hom = η`. +-/ +structure IsoLift where + /-- The expression for the 2-isomorphism. -/ + e : Mor₂Iso + /-- The expression for the proof that the forward direction of the 2-isomorphism is equal to + the original 2-morphism. -/ + eq : Expr + +/-- Expressions for 2-morphisms. -/ +inductive Mor₂ : Type where + /-- The expression for `Iso.hom`. -/ + | isoHom (e : Expr) (isoLift : IsoLift) (iso : Mor₂Iso) : Mor₂ + /-- The expression for `Iso.inv`. -/ + | isoInv (e : Expr) (isoLift : IsoLift) (iso : Mor₂Iso) : Mor₂ + /-- The expression for the identity `𝟙 f`. -/ + | id (e : Expr) (isoLift : IsoLift) (f : Mor₁) : Mor₂ + /-- The expression for the composition `η ≫ θ`. -/ + | comp (e : Expr) (isoLift? : Option IsoLift) (f g h : Mor₁) (η θ : Mor₂) : Mor₂ + /-- The expression for the left whiskering `f ◁ η` with `η : g ⟶ h`. -/ + | whiskerLeft (e : Expr) (isoLift? : Option IsoLift) (f g h : Mor₁) (η : Mor₂) : Mor₂ + /-- The expression for the right whiskering `η ▷ h` with `η : f ⟶ g`. -/ + | whiskerRight (e : Expr) (isoLift? : Option IsoLift) (f g : Mor₁) (η : Mor₂) (h : Mor₁) : Mor₂ + /-- The expression for the horizontal composition `η ◫ θ` with `η : f₁ ⟶ g₁` and `θ : f₂ ⟶ g₂`. -/ + | horizontalComp (e : Expr) (isoLift? : Option IsoLift) (f₁ g₁ f₂ g₂ : Mor₁) (η θ : Mor₂) : Mor₂ + /-- The expression for the coherence composition `η ⊗≫ θ := η ≫ α ≫ θ` with `η : f ⟶ g` + and `θ : h ⟶ i`. -/ + | coherenceComp (e : Expr) (isoLift? : Option IsoLift) (f g h i : Mor₁) + (α : CoherenceHom) (η θ : Mor₂) : Mor₂ + /-- The expression for an atomic non-structural 2-morphism. -/ + | of (η : Atom) : Mor₂ + deriving Inhabited + +/-- A monad equipped with the ability to construct `Mor₂` terms. -/ +class MkMor₂ (m : Type → Type) where + /-- Construct a `Mor₂` term from a lean expression. -/ + ofExpr (e : Expr) : m Mor₂ + +/-- The underlying lean expression of a 2-morphism. -/ +def Mor₂.e : Mor₂ → Expr + | .isoHom e .. => e + | .isoInv e .. => e + | .id e .. => e + | .comp e .. => e + | .whiskerLeft e .. => e + | .whiskerRight e .. => e + | .horizontalComp e .. => e + | .coherenceComp e .. => e + | .of η => η.e + +/-- `η.isoLift?` is a pair of a 2-isomorphism `η'` and a proof that `η'.hom = η`. If no such `η'` +is found, returns `none`. This function does not seek `IsIso` instance. -/ +def Mor₂.isoLift? : Mor₂ → Option IsoLift + | .isoHom _ isoLift .. => some isoLift + | .isoInv _ isoLift .. => some isoLift + | .id _ isoLift .. => some isoLift + | .comp _ isoLift? .. => isoLift? + | .whiskerLeft _ isoLift? .. => isoLift? + | .whiskerRight _ isoLift? .. => isoLift? + | .horizontalComp _ isoLift? .. => isoLift? + | .coherenceComp _ isoLift? .. => isoLift? + | .of _ => none + +/-- The domain of a 2-morphism. -/ +def Mor₂.srcM {m : Type → Type} [Monad m] [MonadMor₁ m] : Mor₂ → m Mor₁ + | .isoHom _ _ iso => iso.srcM + | .isoInv _ _ iso => iso.tgtM + | .id _ _ f => return f + | .comp _ _ f .. => return f + | .whiskerLeft _ _ f g .. => do comp₁M f g + | .whiskerRight _ _ f _ _ h => do comp₁M f h + | .horizontalComp _ _ f₁ _ f₂ .. => do comp₁M f₁ f₂ + | .coherenceComp _ _ f .. => return f + | .of η => return η.src + +/-- The codomain of a 2-morphism. -/ +def Mor₂.tgtM {m : Type → Type} [Monad m] [MonadMor₁ m] : Mor₂ → m Mor₁ + | .isoHom _ _ iso => iso.tgtM + | .isoInv _ _ iso => iso.srcM + | .id _ _ f => return f + | .comp _ _ _ _ h .. => return h + | .whiskerLeft _ _ f _ h _ => do comp₁M f h + | .whiskerRight _ _ _ g _ h => do comp₁M g h + | .horizontalComp _ _ _ g₁ _ g₂ _ _ => do comp₁M g₁ g₂ + | .coherenceComp _ _ _ _ _ i .. => return i + | .of η => return η.tgt + +/-- A monad equipped with the ability to manipulate 2-morphisms. -/ +class MonadMor₂ (m : Type → Type) where + /-- The expression for `Iso.hom η`. -/ + homM (η : Mor₂Iso) : m Mor₂ + /-- The expression for `Iso.hom η`. -/ + atomHomM (η : AtomIso) : m Atom + /-- The expression for `Iso.inv η`. -/ + invM (η : Mor₂Iso) : m Mor₂ + /-- The expression for `Iso.inv η`. -/ + atomInvM (η : AtomIso) : m Atom + /-- The expression for the identity `𝟙 f`. -/ + id₂M (f : Mor₁) : m Mor₂ + /-- The expression for the composition `η ≫ θ`. -/ + comp₂M (η θ : Mor₂) : m Mor₂ + /-- The expression for the left whiskering `f ◁ η`. -/ + whiskerLeftM (f : Mor₁) (η : Mor₂) : m Mor₂ + /-- The expression for the right whiskering `η ▷ h`. -/ + whiskerRightM (η : Mor₂) (h : Mor₁) : m Mor₂ + /-- The expression for the horizontal composition `η ◫ θ`. -/ + horizontalCompM (η θ : Mor₂) : m Mor₂ + /-- The expression for the coherence composition `η ⊗≫ θ := η ≫ α ≫ θ`. -/ + coherenceCompM (α : CoherenceHom) (η θ : Mor₂) : m Mor₂ + +/-- Type of normalized 1-morphisms `((... ≫ h) ≫ g) ≫ f`. -/ +inductive NormalizedHom : Type + /-- The identity 1-morphism `𝟙 a`. -/ + | nil (e : Mor₁) (a : Obj) : NormalizedHom + /-- The `cons` composes an atomic 1-morphism at the end of a normalized 1-morphism. -/ + | cons (e : Mor₁) : NormalizedHom → Atom₁ → NormalizedHom + deriving Inhabited + +/-- The underlying expression of a normalized 1-morphism. -/ +def NormalizedHom.e : NormalizedHom → Mor₁ + | NormalizedHom.nil e _ => e + | NormalizedHom.cons e _ _ => e + +/-- The domain of a normalized 1-morphism. -/ +def NormalizedHom.src : NormalizedHom → Obj + | NormalizedHom.nil _ a => a + | NormalizedHom.cons _ p _ => p.src + +/-- The codomain of a normalized 1-morphism. -/ +def NormalizedHom.tgt : NormalizedHom → Obj + | NormalizedHom.nil _ a => a + | NormalizedHom.cons _ _ f => f.tgt + +/-- Construct the `NormalizedHom.nil` term in `m`. -/ +def normalizedHom.nilM [MonadMor₁ m] (a : Obj) : m NormalizedHom := do + return NormalizedHom.nil (← id₁M a) a + +/-- Construct a `NormalizedHom.cons` term in `m`. -/ +def NormalizedHom.consM [MonadMor₁ m] (p : NormalizedHom) (f : Atom₁) : + m NormalizedHom := do + return NormalizedHom.cons (← comp₁M p.e (.of f)) p f + +/-- `Context ρ` provides the context for manipulating 2-morphisms in a monoidal category or +bicategory. In particular, we will store `MonoidalCategory` or `Bicategory` instance in a context, +and use this through a reader monad when we construct the lean expressions for 2-morphisms. -/ +class Context (ρ : Type) where + /-- Construct a context from a lean expression for a 2-morphism. -/ + mkContext? : Expr → MetaM (Option ρ) + +export Context (mkContext?) + +/-- Construct a context from a lean expression for a 2-morphism. -/ +def mkContext {ρ : Type} [Context ρ] (e : Expr) : MetaM ρ := do + match ← mkContext? e with + | some c => return c + | none => throwError "failed to construct a monoidal category or bicategory context from {e}" + +/-- The state for the `CoherenceM ρ` monad. -/ +structure State where + /-- The cache for evaluating lean expressions of 1-morphisms into `Mor₁` terms. -/ + cache : PersistentExprMap Mor₁ := {} + +/-- The monad for manipulating 2-morphisms in a monoidal category or bicategory. -/ +abbrev CoherenceM (ρ : Type) := ReaderT ρ <| StateT State MetaM + +/-- Run the `CoherenceM ρ` monad. -/ +def CoherenceM.run {α ρ : Type} (x : CoherenceM ρ α) (ctx : ρ) (s : State := {}) : + MetaM α := do + Prod.fst <$> ReaderT.run x ctx s + +end BicategoryLike + +end Tactic + +end Mathlib diff --git a/Mathlib/Tactic/CategoryTheory/Coherence/Normalize.lean b/Mathlib/Tactic/CategoryTheory/Coherence/Normalize.lean new file mode 100644 index 0000000000000..63738eff6d0a9 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Coherence/Normalize.lean @@ -0,0 +1,586 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Datatypes + +/-! +# Normalization of 2-morphisms in bicategories + +This file provides a function that normalizes 2-morphisms in bicategories. The function also +used to normalize morphisms in monoidal categories. This is used in the string diagram widget given +in `Mathlib.Tactic.StringDiagram`, as well as `monoidal` and `bicategory` tactics. + +We say that the 2-morphism `η` in a bicategory is in normal form if +1. `η` is of the form `α₀ ≫ η₀ ≫ α₁ ≫ η₁ ≫ ... αₘ ≫ ηₘ ≫ αₘ₊₁` where each `αᵢ` is a + structural 2-morphism (consisting of associators and unitors), +2. each `ηᵢ` is a non-structural 2-morphism of the form `f₁ ◁ ... ◁ fₙ ◁ θ`, and +3. `θ` is of the form `ι₁ ◫ ... ◫ ιₗ`, and +4. each `ιᵢ` is of the form `κ ▷ g₁ ▷ ... ▷ gₖ`. + +Note that the horizontal composition `◫` is not currently defined for bicategories. In the monoidal +category setting, the horizontal composition is defined as the `tensorHom`, denoted by `⊗`. + +Note that the structural morphisms `αᵢ` are not necessarily normalized, as the main purpose +is to get a list of the non-structural morphisms out. + +Currently, the primary application of the normalization tactic in mind is drawing string diagrams, +which are graphical representations of morphisms in monoidal categories, in the infoview. When +drawing string diagrams, we often ignore associators and unitors (i.e., drawing morphisms in +strict monoidal categories). On the other hand, in Lean, it is considered difficult to formalize +the concept of strict monoidal categories due to the feature of dependent type theory. The +normalization tactic can remove associators and unitors from the expression, extracting the +necessary data for drawing string diagrams. + +The string diagrams widget is to use Penrose (https://github.com/penrose) via ProofWidget. +However, it should be noted that the normalization procedure in this file does not rely on specific +settings, allowing for broader application. Future plans include the following. At least I (Yuma) +would like to work on these in the future, but it might not be immediate. If anyone is interested, +I would be happy to discuss. + +- Currently, the string diagrams widget only do drawing. It would be better they also generate + proofs. That is, by manipulating the string diagrams displayed in the infoview with a mouse to + generate proofs. In #10581, the string diagram widget only uses the morphisms generated by the + normalization tactic and does not use proof terms ensuring that the original morphism and the + normalized morphism are equal. Proof terms will be necessary for proof generation. + +- There is also the possibility of using homotopy.io (https://github.com/homotopy-io), a graphical + proof assistant for category theory, from Lean. At this point, I have very few ideas regarding + this approach. + +## Main definitions +- `Tactic.BicategoryLike.eval`: Given a Lean expression `e` that represents a morphism in a monoidal +category, this function returns a pair of `⟨e', pf⟩` where `e'` is the normalized expression of `e` +and `pf` is a proof that `e = e'`. + +-/ + +open Lean Meta + +namespace Mathlib.Tactic.BicategoryLike + +section + +/-- Expressions of the form `η ▷ f₁ ▷ ... ▷ fₙ`. -/ +inductive WhiskerRight : Type + /-- Construct the expression for an atomic 2-morphism. -/ + | of (η : Atom) : WhiskerRight + /-- Construct the expression for `η ▷ f`. -/ + | whisker (e : Mor₂) (η : WhiskerRight) (f : Atom₁) : WhiskerRight + deriving Inhabited + +/-- The underlying `Mor₂` term of a `WhiskerRight` term. -/ +def WhiskerRight.e : WhiskerRight → Mor₂ + | .of η => .of η + | .whisker e .. => e + +/-- Expressions of the form `η₁ ⊗ ... ⊗ ηₙ`. -/ +inductive HorizontalComp : Type + | of (η : WhiskerRight) : HorizontalComp + | cons (e : Mor₂) (η : WhiskerRight) (ηs : HorizontalComp) : + HorizontalComp + deriving Inhabited + +/-- The underlying `Mor₂` term of a `HorizontalComp` term. -/ +def HorizontalComp.e : HorizontalComp → Mor₂ + | .of η => η.e + | .cons e .. => e + +/-- Expressions of the form `f₁ ◁ ... ◁ fₙ ◁ η`. -/ +inductive WhiskerLeft : Type + /-- Construct the expression for a right-whiskered 2-morphism. -/ + | of (η : HorizontalComp) : WhiskerLeft + /-- Construct the expression for `f ◁ η`. -/ + | whisker (e : Mor₂) (f : Atom₁) (η : WhiskerLeft) : WhiskerLeft + deriving Inhabited + +/-- The underlying `Mor₂` term of a `WhiskerLeft` term. -/ +def WhiskerLeft.e : WhiskerLeft → Mor₂ + | .of η => η.e + | .whisker e .. => e + +/-- Whether a given 2-isomorphism is structural or not. -/ +def Mor₂Iso.isStructural (α : Mor₂Iso) : Bool := + match α with + | .structuralAtom _ => true + | .comp _ _ _ _ η θ => η.isStructural && θ.isStructural + | .whiskerLeft _ _ _ _ η => η.isStructural + | .whiskerRight _ _ _ η _ => η.isStructural + | .horizontalComp _ _ _ _ _ η θ => η.isStructural && θ.isStructural + | .inv _ _ _ η => η.isStructural + | .coherenceComp _ _ _ _ _ _ η θ => η.isStructural && θ.isStructural + | .of _ => false + +/-- Expressions for structural isomorphisms. We do not impose the condition `isStructural` since +it is not needed to write the tactic. -/ +abbrev Structural := Mor₂Iso + +/-- Normalized expressions for 2-morphisms. -/ +inductive NormalExpr : Type + /-- Construct the expression for a structural 2-morphism. -/ + | nil (e : Mor₂) (α : Structural) : NormalExpr + /-- Construct the normalized expression of a 2-morphism `α ≫ η ≫ ηs` recursively. -/ + | cons (e : Mor₂) (α : Structural) (η : WhiskerLeft) (ηs : NormalExpr) : NormalExpr + deriving Inhabited + +/-- The underlying `Mor₂` term of a `NormalExpr` term. -/ +def NormalExpr.e : NormalExpr → Mor₂ + | .nil e .. => e + | .cons e .. => e + +/-- A monad equipped with the ability to construct `WhiskerRight` terms. -/ +class MonadWhiskerRight (m : Type → Type) where + /-- The expression for the right whiskering `η ▷ f`. -/ + whiskerRightM (η : WhiskerRight) (f : Atom₁) : m WhiskerRight + +/-- A monad equipped with the ability to construct `HorizontalComp` terms. -/ +class MonadHorizontalComp (m : Type → Type) extends MonadWhiskerRight m where + /-- The expression for the horizontal composition `η ◫ ηs`. -/ + hConsM (η : WhiskerRight) (ηs : HorizontalComp) : m HorizontalComp + +/-- A monad equipped with the ability to construct `WhiskerLeft` terms. -/ +class MonadWhiskerLeft (m : Type → Type) extends MonadHorizontalComp m where + /-- The expression for the left whiskering `f ▷ η`. -/ + whiskerLeftM (f : Atom₁) (η : WhiskerLeft) : m WhiskerLeft + +/-- A monad equipped with the ability to construct `NormalExpr` terms. -/ +class MonadNormalExpr (m : Type → Type) extends MonadWhiskerLeft m where + /-- The expression for the structural 2-morphism `α`. -/ + nilM (α : Structural) : m NormalExpr + /-- The expression for the normalized 2-morphism `α ≫ η ≫ ηs`. -/ + consM (headStructural : Structural) (η : WhiskerLeft) (ηs : NormalExpr) : m NormalExpr + +variable {m : Type → Type} [Monad m] + +open MonadMor₁ + +/-- The domain of a 2-morphism. -/ +def WhiskerRight.srcM [MonadMor₁ m] : WhiskerRight → m Mor₁ + | WhiskerRight.of η => return η.src + | WhiskerRight.whisker _ η f => do comp₁M (← η.srcM) (.of f) + +/-- The codomain of a 2-morphism. -/ +def WhiskerRight.tgtM [MonadMor₁ m] : WhiskerRight → m Mor₁ + | WhiskerRight.of η => return η.tgt + | WhiskerRight.whisker _ η f => do comp₁M (← η.tgtM) (.of f) + +/-- The domain of a 2-morphism. -/ +def HorizontalComp.srcM [MonadMor₁ m] : HorizontalComp → m Mor₁ + | HorizontalComp.of η => η.srcM + | HorizontalComp.cons _ η ηs => do comp₁M (← η.srcM) (← ηs.srcM) + +/-- The codomain of a 2-morphism. -/ +def HorizontalComp.tgtM [MonadMor₁ m] : HorizontalComp → m Mor₁ + | HorizontalComp.of η => η.tgtM + | HorizontalComp.cons _ η ηs => do comp₁M (← η.tgtM) (← ηs.tgtM) + +/-- The domain of a 2-morphism. -/ +def WhiskerLeft.srcM [MonadMor₁ m] : WhiskerLeft → m Mor₁ + | WhiskerLeft.of η => η.srcM + | WhiskerLeft.whisker _ f η => do comp₁M (.of f) (← η.srcM) + +/-- The codomain of a 2-morphism. -/ +def WhiskerLeft.tgtM [MonadMor₁ m] : WhiskerLeft → m Mor₁ + | WhiskerLeft.of η => η.tgtM + | WhiskerLeft.whisker _ f η => do comp₁M (.of f) (← η.tgtM) + +/-- The domain of a 2-morphism. -/ +def NormalExpr.srcM [MonadMor₁ m] : NormalExpr → m Mor₁ + | NormalExpr.nil _ η => η.srcM + | NormalExpr.cons _ α _ _ => α.srcM + +/-- The codomain of a 2-morphism. -/ +def NormalExpr.tgtM [MonadMor₁ m] : NormalExpr → m Mor₁ + | NormalExpr.nil _ η => η.tgtM + | NormalExpr.cons _ _ _ ηs => ηs.tgtM + +namespace NormalExpr + +variable [MonadMor₂Iso m] [MonadNormalExpr m] + +/-- The identity 2-morphism as a term of `normalExpr`. -/ +def idM (f : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| .structuralAtom <| ← MonadMor₂Iso.id₂M f + +/-- The associator as a term of `normalExpr`. -/ +def associatorM (f g h : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| .structuralAtom <| ← MonadMor₂Iso.associatorM f g h + +/-- The inverse of the associator as a term of `normalExpr`. -/ +def associatorInvM (f g h : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| ← MonadMor₂Iso.symmM <| + .structuralAtom <| ← MonadMor₂Iso.associatorM f g h + +/-- The left unitor as a term of `normalExpr`. -/ +def leftUnitorM (f : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| .structuralAtom <| ← MonadMor₂Iso.leftUnitorM f + +/-- The inverse of the left unitor as a term of `normalExpr`. -/ +def leftUnitorInvM (f : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| ← MonadMor₂Iso.symmM <| .structuralAtom <| ← MonadMor₂Iso.leftUnitorM f + +/-- The right unitor as a term of `normalExpr`. -/ +def rightUnitorM (f : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| .structuralAtom <| ← MonadMor₂Iso.rightUnitorM f + +/-- The inverse of the right unitor as a term of `normalExpr`. -/ +def rightUnitorInvM (f : Mor₁) : m NormalExpr := do + MonadNormalExpr.nilM <| ← MonadMor₂Iso.symmM <| .structuralAtom <| ← MonadMor₂Iso.rightUnitorM f + +/-- Construct a `NormalExpr` expression from a `WhiskerLeft` expression. -/ +def ofM [MonadMor₁ m] (η : WhiskerLeft) : m NormalExpr := do + MonadNormalExpr.consM ((.structuralAtom <| ← MonadMor₂Iso.id₂M (← η.srcM))) η + (← MonadNormalExpr.nilM ((.structuralAtom <| ← MonadMor₂Iso.id₂M (← η.tgtM)))) + +/-- Construct a `NormalExpr` expression from a Lean expression for an atomic 2-morphism. -/ +def ofAtomM [MonadMor₁ m] (η : Atom) : m NormalExpr := + NormalExpr.ofM <| .of <| .of <| .of η + +end NormalExpr + +/-- Convert a `NormalExpr` expression into a list of `WhiskerLeft` expressions. -/ +def NormalExpr.toList : NormalExpr → List WhiskerLeft + | NormalExpr.nil _ _ => [] + | NormalExpr.cons _ _ η ηs => η :: NormalExpr.toList ηs + +end + +section + +/-- The result of evaluating an expression into normal form. -/ +structure Eval.Result where + /-- The normalized expression of the 2-morphism. -/ + expr : NormalExpr + /-- The proof that the normalized expression is equal to the original expression. -/ + proof : Expr + deriving Inhabited + +variable {m : Type → Type} [Monad m] + +/-- Evaluate the expression `α ≫ β`. -/ +class MkEvalComp (m : Type → Type) where + /-- Evaluate `α ≫ β` -/ + mkEvalCompNilNil (α β : Structural) : m Expr + /-- Evaluate `α ≫ (β ≫ η ≫ ηs)` -/ + mkEvalCompNilCons (α β : Structural) (η : WhiskerLeft) (ηs : NormalExpr) : m Expr + /-- Evaluate `(α ≫ η ≫ ηs) ≫ θ` -/ + mkEvalCompCons (α : Structural) (η : WhiskerLeft) (ηs θ ι : NormalExpr) (e_η : Expr) : m Expr + +/-- Evaluatte the expression `f ◁ η`. -/ +class MkEvalWhiskerLeft (m : Type → Type) where + /-- Evaluatte `f ◁ α` -/ + mkEvalWhiskerLeftNil (f : Mor₁) (α : Structural) : m Expr + /-- Evaluate `f ◁ (α ≫ η ≫ ηs)`. -/ + mkEvalWhiskerLeftOfCons (f : Atom₁) (α : Structural) (η : WhiskerLeft) (ηs θ : NormalExpr) + (e_θ : Expr) : m Expr + /-- Evaluate `(f ≫ g) ◁ η` -/ + mkEvalWhiskerLeftComp (f g : Mor₁) (η η₁ η₂ η₃ η₄ : NormalExpr) + (e_η₁ e_η₂ e_η₃ e_η₄ : Expr) : m Expr + /-- Evaluate `𝟙 _ ◁ η` -/ + mkEvalWhiskerLeftId (η η₁ η₂ : NormalExpr) (e_η₁ e_η₂ : Expr) : m Expr + +/-- Evaluate the expression `η ▷ f`. -/ +class MkEvalWhiskerRight (m : Type → Type) where + /-- Evaluate `η ▷ f` -/ + mkEvalWhiskerRightAuxOf (η : WhiskerRight) (f : Atom₁) : m Expr + /-- Evaluate `(η ◫ ηs) ▷ f` -/ + mkEvalWhiskerRightAuxCons (f : Atom₁) (η : WhiskerRight) (ηs : HorizontalComp) + (ηs' η₁ η₂ η₃ : NormalExpr) (e_ηs' e_η₁ e_η₂ e_η₃ : Expr) : m Expr + /-- Evaluate `α ▷ f` -/ + mkEvalWhiskerRightNil (α : Structural) (f : Mor₁) : m Expr + /-- Evaluate ` (α ≫ η ≫ ηs) ▷ j` -/ + mkEvalWhiskerRightConsOfOf (f : Atom₁) (α : Structural) (η : HorizontalComp) + (ηs ηs₁ η₁ η₂ η₃ : NormalExpr) + (e_ηs₁ e_η₁ e_η₂ e_η₃ : Expr) : m Expr + /-- Evaluate `(α ≫ (f ◁ η) ≫ ηs) ▷ g` -/ + mkEvalWhiskerRightConsWhisker (f : Atom₁) (g : Mor₁) (α : Structural) (η : WhiskerLeft) + (ηs η₁ η₂ ηs₁ ηs₂ η₃ η₄ η₅ : NormalExpr) (e_η₁ e_η₂ e_ηs₁ e_ηs₂ e_η₃ e_η₄ e_η₅ : Expr) : m Expr + /-- Evaluate `η ▷ (g ⊗ h)` -/ + mkEvalWhiskerRightComp (g h : Mor₁) + (η η₁ η₂ η₃ η₄ : NormalExpr) (e_η₁ e_η₂ e_η₃ e_η₄ : Expr) : m Expr + /-- Evaluate `η ▷ 𝟙 _` -/ + mkEvalWhiskerRightId (η η₁ η₂ : NormalExpr) (e_η₁ e_η₂ : Expr) : m Expr + +/-- Evaluate the expression `η ◫ θ`. -/ +class MkEvalHorizontalComp (m : Type → Type) where + /-- Evaluate `η ◫ θ` -/ + mkEvalHorizontalCompAuxOf (η : WhiskerRight) (θ : HorizontalComp) : m Expr + /-- Evaluate `(η ◫ ηs) ◫ θ` -/ + mkEvalHorizontalCompAuxCons (η : WhiskerRight) (ηs θ : HorizontalComp) + (ηθ η₁ ηθ₁ ηθ₂ : NormalExpr) (e_ηθ e_η₁ e_ηθ₁ e_ηθ₂ : Expr) : m Expr + /-- Evaluate `(f ◁ η) ◫ θ` -/ + mkEvalHorizontalCompAux'Whisker (f : Atom₁) (η θ : WhiskerLeft) + (ηθ ηθ₁ ηθ₂ ηθ₃ : NormalExpr) (e_ηθ e_ηθ₁ e_ηθ₂ e_ηθ₃ : Expr) : m Expr + /-- Evaluate `η ◫ (f ◁ θ)` -/ + mkEvalHorizontalCompAux'OfWhisker (f : Atom₁) (η : HorizontalComp) (θ : WhiskerLeft) + (η₁ ηθ ηθ₁ ηθ₂ : NormalExpr) (e_ηθ e_η₁ e_ηθ₁ e_ηθ₂ : Expr) : m Expr + /-- Evaluate `α ◫ β` -/ + mkEvalHorizontalCompNilNil (α β : Structural) : m Expr + /-- Evaluate `α ◫ (β ≫ η ≫ ηs)` -/ + mkEvalHorizontalCompNilCons (α β : Structural) (η : WhiskerLeft) + (ηs η₁ ηs₁ η₂ η₃ : NormalExpr) (e_η₁ e_ηs₁ e_η₂ e_η₃ : Expr) : m Expr + /-- Evaluate `(α ≫ η ≫ ηs) ◫ β` -/ + mkEvalHorizontalCompConsNil (α β : Structural) (η : WhiskerLeft) (ηs : NormalExpr) + (η₁ ηs₁ η₂ η₃ : NormalExpr) (e_η₁ e_ηs₁ e_η₂ e_η₃ : Expr) : m Expr + /-- Evaluate `(α ≫ η ≫ ηs) ◫ (β ≫ θ ≫ θs)` -/ + mkEvalHorizontalCompConsCons (α β : Structural) (η θ : WhiskerLeft) + (ηs θs ηθ ηθs ηθ₁ ηθ₂ : NormalExpr) (e_ηθ e_ηθs e_ηθ₁ e_ηθ₂ : Expr) : m Expr + +/-- Evaluate the expression of a 2-morphism into a normalized form. -/ +class MkEval (m : Type → Type) extends + MkEvalComp m, MkEvalWhiskerLeft m, MkEvalWhiskerRight m, MkEvalHorizontalComp m where + /-- Evaluate the expression `η ≫ θ` into a normalized form. -/ + mkEvalComp (η θ : Mor₂) (η' θ' ηθ : NormalExpr) (e_η e_θ e_ηθ : Expr) : m Expr + /-- Evaluate the expression `f ◁ η` into a normalized form. -/ + mkEvalWhiskerLeft (f : Mor₁) (η : Mor₂) (η' θ : NormalExpr) (e_η e_θ : Expr) : m Expr + /-- Evaluate the expression `η ▷ f` into a normalized form. -/ + mkEvalWhiskerRight (η : Mor₂) (h : Mor₁) (η' θ : NormalExpr) (e_η e_θ : Expr) : m Expr + /-- Evaluate the expression `η ◫ θ` into a normalized form. -/ + mkEvalHorizontalComp (η θ : Mor₂) (η' θ' ι : NormalExpr) (e_η e_θ e_ι : Expr) : m Expr + /-- Evaluate the atomic 2-morphism `η` into a normalized form. -/ + mkEvalOf (η : Atom) : m Expr + /-- Evaluate the expression `η ⊗≫ θ := η ≫ α ≫ θ` into a normalized form. -/ + mkEvalMonoidalComp (η θ : Mor₂) (α : Structural) (η' θ' αθ ηαθ : NormalExpr) + (e_η e_θ e_αθ e_ηαθ : Expr) : m Expr + +variable {ρ : Type} [Context ρ] +variable [MonadMor₂Iso (CoherenceM ρ)] [MonadNormalExpr (CoherenceM ρ)] [MkEval (CoherenceM ρ)] + +open MkEvalComp MonadMor₂Iso MonadNormalExpr + +/-- Evaluate the expression `α ≫ η` into a normalized form. -/ +def evalCompNil (α : Structural) : NormalExpr → CoherenceM ρ Eval.Result + | .nil _ β => do return ⟨← nilM (← comp₂M α β), ← mkEvalCompNilNil α β⟩ + | .cons _ β η ηs => do return ⟨← consM (← comp₂M α β) η ηs, ← mkEvalCompNilCons α β η ηs⟩ + +/-- Evaluate the expression `η ≫ θ` into a normalized form. -/ +def evalComp : NormalExpr → NormalExpr → CoherenceM ρ Eval.Result + | .nil _ α, η => do evalCompNil α η + | .cons _ α η ηs, θ => do + let ⟨ι, e_ι⟩ ← evalComp ηs θ + return ⟨← consM α η ι, ← mkEvalCompCons α η ηs θ ι e_ι⟩ + +open MkEvalWhiskerLeft + +variable [MonadMor₁ (CoherenceM ρ)] [MonadMor₂Iso (CoherenceM ρ)] + +/-- Evaluate the expression `f ◁ η` into a normalized form. -/ +def evalWhiskerLeft : Mor₁ → NormalExpr → CoherenceM ρ Eval.Result + | f, .nil _ α => do + return ⟨← nilM (← whiskerLeftM f α), ← mkEvalWhiskerLeftNil f α⟩ + | .of f, .cons _ α η ηs => do + let η' ← MonadWhiskerLeft.whiskerLeftM f η + let ⟨θ, e_θ⟩ ← evalWhiskerLeft (.of f) ηs + let η'' ← consM (← whiskerLeftM (.of f) α) η' θ + return ⟨η'', ← mkEvalWhiskerLeftOfCons f α η ηs θ e_θ⟩ + | .comp _ f g, η => do + let ⟨θ, e_θ⟩ ← evalWhiskerLeft g η + let ⟨ι, e_ι⟩ ← evalWhiskerLeft f θ + let h ← η.srcM + let h' ← η.tgtM + let ⟨ι', e_ι'⟩ ← evalComp ι (← NormalExpr.associatorInvM f g h') + let ⟨ι'', e_ι''⟩ ← evalComp (← NormalExpr.associatorM f g h) ι' + return ⟨ι'', ← mkEvalWhiskerLeftComp f g η θ ι ι' ι'' e_θ e_ι e_ι' e_ι''⟩ + | .id _ _, η => do + let f ← η.srcM + let g ← η.tgtM + let ⟨η', e_η'⟩ ← evalComp η (← NormalExpr.leftUnitorInvM g) + let ⟨η'', e_η''⟩ ← evalComp (← NormalExpr.leftUnitorM f) η' + return ⟨η'', ← mkEvalWhiskerLeftId η η' η'' e_η' e_η''⟩ + +open MkEvalWhiskerRight MkEvalHorizontalComp + +mutual + +/-- Evaluate the expression `η ▷ f` into a normalized form. -/ +partial def evalWhiskerRightAux : HorizontalComp → Atom₁ → CoherenceM ρ Eval.Result + | .of η, f => do + let η' ← NormalExpr.ofM <| .of <| .of <| ← MonadWhiskerRight.whiskerRightM η f + return ⟨η', ← mkEvalWhiskerRightAuxOf η f⟩ + | .cons _ η ηs, f => do + let ⟨ηs', e_ηs'⟩ ← evalWhiskerRightAux ηs f + let ⟨η₁, e_η₁⟩ ← evalHorizontalComp (← NormalExpr.ofM <| .of <| .of η) ηs' + let ⟨η₂, e_η₂⟩ ← evalComp η₁ (← NormalExpr.associatorInvM (← η.tgtM) (← ηs.tgtM) (.of f)) + let ⟨η₃, e_η₃⟩ ← evalComp (← NormalExpr.associatorM (← η.srcM) (← ηs.srcM) (.of f)) η₂ + return ⟨η₃, ← mkEvalWhiskerRightAuxCons f η ηs ηs' η₁ η₂ η₃ e_ηs' e_η₁ e_η₂ e_η₃⟩ + +/-- Evaluate the expression `η ▷ f` into a normalized form. -/ +partial def evalWhiskerRight : NormalExpr → Mor₁ → CoherenceM ρ Eval.Result + | .nil _ α, h => do + return ⟨← nilM (← whiskerRightM α h), ← mkEvalWhiskerRightNil α h⟩ + | .cons _ α (.of η) ηs, .of f => do + let ⟨ηs₁, e_ηs₁⟩ ← evalWhiskerRight ηs (.of f) + let ⟨η₁, e_η₁⟩ ← evalWhiskerRightAux η f + let ⟨η₂, e_η₂⟩ ← evalComp η₁ ηs₁ + let ⟨η₃, e_η₃⟩ ← evalCompNil (← whiskerRightM α (.of f)) η₂ + return ⟨η₃, ← mkEvalWhiskerRightConsOfOf f α η ηs ηs₁ η₁ η₂ η₃ e_ηs₁ e_η₁ e_η₂ e_η₃⟩ + | .cons _ α (.whisker _ f η) ηs, h => do + let g ← η.srcM + let g' ← η.tgtM + let ⟨η₁, e_η₁⟩ ← evalWhiskerRight (← consM (← id₂M' g) η (← NormalExpr.idM g')) h + let ⟨η₂, e_η₂⟩ ← evalWhiskerLeft (.of f) η₁ + let ⟨ηs₁, e_ηs₁⟩ ← evalWhiskerRight ηs h + let α' ← whiskerRightM α h + let ⟨ηs₂, e_ηs₂⟩ ← evalComp (← NormalExpr.associatorInvM (.of f) g' h) ηs₁ + let ⟨η₃, e_η₃⟩ ← evalComp η₂ ηs₂ + let ⟨η₄, e_η₄⟩ ← evalComp (← NormalExpr.associatorM (.of f) g h) η₃ + let ⟨η₅, e_η₅⟩ ← evalComp (← nilM α') η₄ + return ⟨η₅, ← mkEvalWhiskerRightConsWhisker f h α η ηs η₁ η₂ ηs₁ ηs₂ η₃ η₄ η₅ + e_η₁ e_η₂ e_ηs₁ e_ηs₂ e_η₃ e_η₄ e_η₅⟩ + | η, .comp _ g h => do + let ⟨η₁, e_η₁⟩ ← evalWhiskerRight η g + let ⟨η₂, e_η₂⟩ ← evalWhiskerRight η₁ h + let f ← η.srcM + let f' ← η.tgtM + let ⟨η₃, e_η₃⟩ ← evalComp η₂ (← NormalExpr.associatorM f' g h) + let ⟨η₄, e_η₄⟩ ← evalComp (← NormalExpr.associatorInvM f g h) η₃ + return ⟨η₄, ← mkEvalWhiskerRightComp g h η η₁ η₂ η₃ η₄ e_η₁ e_η₂ e_η₃ e_η₄⟩ + | η, .id _ _ => do + let f ← η.srcM + let g ← η.tgtM + let ⟨η₁, e_η₁⟩ ← evalComp η (← NormalExpr.rightUnitorInvM g) + let ⟨η₂, e_η₂⟩ ← evalComp (← NormalExpr.rightUnitorM f) η₁ + return ⟨η₂, ← mkEvalWhiskerRightId η η₁ η₂ e_η₁ e_η₂⟩ + +/-- Evaluate the expression `η ⊗ θ` into a normalized form. -/ +partial def evalHorizontalCompAux : HorizontalComp → HorizontalComp → CoherenceM ρ Eval.Result + | .of η, θ => do + return ⟨← NormalExpr.ofM <| .of <| ← MonadHorizontalComp.hConsM η θ, + ← mkEvalHorizontalCompAuxOf η θ⟩ + | .cons _ η ηs, θ => do + let α ← NormalExpr.associatorM (← η.srcM) (← ηs.srcM) (← θ.srcM) + let α' ← NormalExpr.associatorInvM (← η.tgtM) (← ηs.tgtM) (← θ.tgtM) + let ⟨ηθ, e_ηθ⟩ ← evalHorizontalCompAux ηs θ + let ⟨η₁, e_η₁⟩ ← evalHorizontalComp (← NormalExpr.ofM <| .of <| .of η) ηθ + let ⟨ηθ₁, e_ηθ₁⟩ ← evalComp η₁ α' + let ⟨ηθ₂, e_ηθ₂⟩ ← evalComp α ηθ₁ + return ⟨ηθ₂, ← mkEvalHorizontalCompAuxCons η ηs θ ηθ η₁ ηθ₁ ηθ₂ e_ηθ e_η₁ e_ηθ₁ e_ηθ₂⟩ + +/-- Evaluate the expression `η ⊗ θ` into a normalized form. -/ +partial def evalHorizontalCompAux' : WhiskerLeft → WhiskerLeft → CoherenceM ρ Eval.Result + | .of η, .of θ => evalHorizontalCompAux η θ + | .whisker _ f η, θ => do + let ⟨ηθ, e_ηθ⟩ ← evalHorizontalCompAux' η θ + let ⟨ηθ₁, e_ηθ₁⟩ ← evalWhiskerLeft (.of f) ηθ + let ⟨ηθ₂, e_ηθ₂⟩ ← evalComp ηθ₁ (← NormalExpr.associatorInvM (.of f) (← η.tgtM) (← θ.tgtM)) + let ⟨ηθ₃, e_ηθ₃⟩ ← evalComp (← NormalExpr.associatorM (.of f) (← η.srcM) (← θ.srcM)) ηθ₂ + return ⟨ηθ₃, ← mkEvalHorizontalCompAux'Whisker f η θ ηθ ηθ₁ ηθ₂ ηθ₃ e_ηθ e_ηθ₁ e_ηθ₂ e_ηθ₃⟩ + | .of η, .whisker _ f θ => do + let ⟨η₁, e_η₁⟩ ← evalWhiskerRightAux η f + let ⟨ηθ, e_ηθ⟩ ← evalHorizontalComp η₁ (← NormalExpr.ofM θ) + let ⟨ηθ₁, e_ηθ₁⟩ ← evalComp ηθ (← NormalExpr.associatorM (← η.tgtM) (.of f) (← θ.tgtM)) + let ⟨ηθ₂, e_ηθ₂⟩ ← evalComp (← NormalExpr.associatorInvM (← η.srcM) (.of f) (← θ.srcM)) ηθ₁ + return ⟨ηθ₂, ← mkEvalHorizontalCompAux'OfWhisker f η θ ηθ η₁ ηθ₁ ηθ₂ e_η₁ e_ηθ e_ηθ₁ e_ηθ₂⟩ + +/-- Evaluate the expression `η ⊗ θ` into a normalized form. -/ +partial def evalHorizontalComp : NormalExpr → NormalExpr → CoherenceM ρ Eval.Result + | .nil _ α, .nil _ β => do + return ⟨← nilM <| ← horizontalCompM α β, ← mkEvalHorizontalCompNilNil α β⟩ + | .nil _ α, .cons _ β η ηs => do + let ⟨η₁, e_η₁⟩ ← evalWhiskerLeft (← α.tgtM) (← NormalExpr.ofM η) + let ⟨ηs₁, e_ηs₁⟩ ← evalWhiskerLeft (← α.tgtM) ηs + let ⟨η₂, e_η₂⟩ ← evalComp η₁ ηs₁ + let ⟨η₃, e_η₃⟩ ← evalCompNil (← horizontalCompM α β) η₂ + return ⟨η₃, ← mkEvalHorizontalCompNilCons α β η ηs η₁ ηs₁ η₂ η₃ e_η₁ e_ηs₁ e_η₂ e_η₃⟩ + | .cons _ α η ηs, .nil _ β => do + let ⟨η₁, e_η₁⟩ ← evalWhiskerRight (← NormalExpr.ofM η) (← β.tgtM) + let ⟨ηs₁, e_ηs₁⟩ ← evalWhiskerRight ηs (← β.tgtM) + let ⟨η₂, e_η₂⟩ ← evalComp η₁ ηs₁ + let ⟨η₃, e_η₃⟩ ← evalCompNil (← horizontalCompM α β) η₂ + return ⟨η₃, ← mkEvalHorizontalCompConsNil α β η ηs η₁ ηs₁ η₂ η₃ e_η₁ e_ηs₁ e_η₂ e_η₃⟩ + | .cons _ α η ηs, .cons _ β θ θs => do + let ⟨ηθ, e_ηθ⟩ ← evalHorizontalCompAux' η θ + let ⟨ηθs, e_ηθs⟩ ← evalHorizontalComp ηs θs + let ⟨ηθ₁, e_ηθ₁⟩ ← evalComp ηθ ηθs + let ⟨ηθ₂, e_ηθ₂⟩ ← evalCompNil (← horizontalCompM α β) ηθ₁ + return ⟨ηθ₂, + ← mkEvalHorizontalCompConsCons α β η θ ηs θs ηθ ηθs ηθ₁ ηθ₂ e_ηθ e_ηθs e_ηθ₁ e_ηθ₂⟩ + +end + +open MkEval + +variable {ρ : Type} [Context ρ] + [MonadMor₁ (CoherenceM ρ)] + [MonadMor₂Iso (CoherenceM ρ)] + [MonadNormalExpr (CoherenceM ρ)] [MkEval (CoherenceM ρ)] + [MonadMor₂ (CoherenceM ρ)] + [MkMor₂ (CoherenceM ρ)] + +/-- Trace the proof of the normalization. -/ +def traceProof (nm : Name) (result : Expr) : CoherenceM ρ Unit := do + withTraceNode nm (fun _ => return m!"{checkEmoji} {← inferType result}") do + if ← isTracingEnabledFor nm then addTrace nm m!"proof: {result}" + +-- TODO: It takes a while to compile. Find out why. +/-- Evaluate the expression of a 2-morphism into a normalized form. -/ +def eval (nm : Name) (e : Mor₂) : CoherenceM ρ Eval.Result := do + withTraceNode nm (fun _ => return m!"eval: {e.e}") do + match e with + | .isoHom _ _ α => withTraceNode nm (fun _ => return m!"Iso.hom") do match α with + | .structuralAtom α => return ⟨← nilM <| .structuralAtom α, ← mkEqRefl e.e⟩ + | .of η => + let η ← MonadMor₂.atomHomM η + let result ← mkEvalOf η + traceProof nm result + return ⟨← NormalExpr.ofAtomM η, result⟩ + | _ => throwError "not implemented. try dsimp first." + | .isoInv _ _ α => withTraceNode nm (fun _ => return m!"Iso.inv") do match α with + | .structuralAtom α => return ⟨← nilM <| (← symmM (.structuralAtom α)), ← mkEqRefl e.e⟩ + | .of η => + let η ← MonadMor₂.atomInvM η + let result ← mkEvalOf η + traceProof nm result + return ⟨← NormalExpr.ofAtomM η, result⟩ + | _ => throwError "not implemented. try dsimp first." + | .id _ _ f => + let α ← MonadMor₂Iso.id₂M f + return ⟨← nilM <| .structuralAtom α, ← mkEqRefl e.e⟩ + | .comp _ _ _ _ _ η θ => withTraceNode nm (fun _ => return m!"comp") do + let ⟨η', e_η⟩ ← eval nm η + let ⟨θ', e_θ⟩ ← eval nm θ + let ⟨ηθ, pf⟩ ← evalComp η' θ' + let result ← mkEvalComp η θ η' θ' ηθ e_η e_θ pf + traceProof nm result + return ⟨ηθ, result⟩ + | .whiskerLeft _ _ f _ _ η => withTraceNode nm (fun _ => return m!"whiskerLeft") do + let ⟨η', e_η⟩ ← eval nm η + let ⟨θ, e_θ⟩ ← evalWhiskerLeft f η' + let result ← mkEvalWhiskerLeft f η η' θ e_η e_θ + traceProof nm result + return ⟨θ, result⟩ + | .whiskerRight _ _ _ _ η h => + withTraceNode nm (fun _ => return m!"whiskerRight") do + let ⟨η', e_η⟩ ← eval nm η + let ⟨θ, e_θ⟩ ← evalWhiskerRight η' h + let result ← mkEvalWhiskerRight η h η' θ e_η e_θ + traceProof nm result + return ⟨θ, result⟩ + | .coherenceComp _ _ _ _ _ _ α₀ η θ => + withTraceNode nm (fun _ => return m!"monoidalComp") do + let ⟨η', e_η⟩ ← eval nm η + let α₀ := .structuralAtom <| .coherenceHom α₀ + let α ← nilM α₀ + let ⟨θ', e_θ⟩ ← eval nm θ + let ⟨αθ, e_αθ⟩ ← evalComp α θ' + let ⟨ηαθ, e_ηαθ⟩ ← evalComp η' αθ + let result ← mkEvalMonoidalComp η θ α₀ η' θ' αθ ηαθ e_η e_θ e_αθ e_ηαθ + traceProof nm result + return ⟨ηαθ, result⟩ + | .horizontalComp _ _ _ _ _ _ η θ => + withTraceNode nm (fun _ => return m!"horizontalComp") do + let ⟨η', e_η⟩ ← eval nm η + let ⟨θ', e_θ⟩ ← eval nm θ + let ⟨ηθ, e_ηθ⟩ ← evalHorizontalComp η' θ' + let result ← mkEvalHorizontalComp η θ η' θ' ηθ e_η e_θ e_ηθ + traceProof nm result + return ⟨ηθ, result⟩ + | .of η => + let result ← mkEvalOf η + traceProof nm result + return ⟨← NormalExpr.ofAtomM η, result⟩ + +end + +end Mathlib.Tactic.BicategoryLike diff --git a/Mathlib/Tactic/CategoryTheory/Coherence/PureCoherence.lean b/Mathlib/Tactic/CategoryTheory/Coherence/PureCoherence.lean new file mode 100644 index 0000000000000..fb4cf07da5033 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Coherence/PureCoherence.lean @@ -0,0 +1,197 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Datatypes + +/-! +# Coherence tactic + +This file provides a meta framework for the coherence tactic, which solves goals of the form +`η = θ`, where `η` and `θ` are 2-morphism in a bicategory or morphisms in a monoidal category +made up only of associators, unitors, and identities. + +The function defined here is a meta reimplementation of the formalized coherence theorems provided +in the following files: +- Mathlib.CategoryTheory.Monoidal.Free.Coherence +- Mathlib.CategoryTheory.Bicategory.Coherence +See these files for a mathematical explanation of the proof of the coherence theorem. + +The actual tactics that users will use are given in +- `Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence` +- `Mathlib.Tactic.CategoryTheory.Bicategory.PureCoherence` + +-/ + +open Lean Meta + +namespace Mathlib.Tactic + +namespace BicategoryLike + +/-- The result of normalizing a 1-morphism. -/ +structure Normalize.Result where + /-- The normalized 1-morphism. -/ + normalizedHom : NormalizedHom + /-- The 2-morphism from the original 1-morphism to the normalized 1-morphism. -/ + toNormalize : Mor₂Iso + deriving Inhabited + +open Mor₂Iso MonadMor₂Iso + +variable {ρ : Type} [Context ρ] [MonadMor₁ (CoherenceM ρ)] [MonadMor₂Iso (CoherenceM ρ)] + +/-- Meta version of `CategoryTheory.FreeBicategory.normalizeIso`. -/ +def normalize (p : NormalizedHom) (f : Mor₁) : + CoherenceM ρ Normalize.Result := do + match f with + | .id _ _ => + return ⟨p, ← rightUnitorM' p.e⟩ + | .comp _ f g => + let ⟨pf, η_f⟩ ← normalize p f + let η_f' ← whiskerRightM η_f g + let ⟨pfg, η_g⟩ ← normalize pf g + let η ← comp₂M η_f' η_g + let α ← symmM (← associatorM' p.e f g) + let η' ← comp₂M α η + return ⟨pfg, η'⟩ + | .of f => + let pf ← NormalizedHom.consM p f + let α ← id₂M' pf.e + return ⟨pf, α⟩ + +/-- Lemmas to prove the meta version of `CategoryTheory.FreeBicategory.normalize_naturality`. -/ +class MonadNormalizeNaturality (m : Type → Type) where + /-- The naturality for the associator. -/ + mkNaturalityAssociator (p pf pfg pfgh : NormalizedHom) (f g h : Mor₁) + (η_f η_g η_h : Mor₂Iso) : m Expr + /-- The naturality for the left unitor. -/ + mkNaturalityLeftUnitor (p pf : NormalizedHom) (f : Mor₁) (η_f : Mor₂Iso) : m Expr + /-- The naturality for the right unitor. -/ + mkNaturalityRightUnitor (p pf : NormalizedHom) (f : Mor₁) (η_f : Mor₂Iso) : m Expr + /-- The naturality for the identity. -/ + mkNaturalityId (p pf : NormalizedHom) (f : Mor₁) (η_f : Mor₂Iso) : m Expr + /-- The naturality for the composition. -/ + mkNaturalityComp (p pf : NormalizedHom) (f g h : Mor₁) (η θ η_f η_g η_h : Mor₂Iso) + (ih_η ih_θ : Expr) : m Expr + /-- The naturality for the left whiskering. -/ + mkNaturalityWhiskerLeft (p pf pfg : NormalizedHom) (f g h : Mor₁) + (η η_f η_fg η_fh : Mor₂Iso) (ih_η : Expr) : m Expr + /-- The naturality for the right whiskering. -/ + mkNaturalityWhiskerRight (p pf pfh : NormalizedHom) (f g h : Mor₁) (η η_f η_g η_fh : Mor₂Iso) + (ih_η : Expr) : m Expr + /-- The naturality for the horizontal composition. -/ + mkNaturalityHorizontalComp (p pf₁ pf₁f₂ : NormalizedHom) (f₁ g₁ f₂ g₂ : Mor₁) + (η θ η_f₁ η_g₁ η_f₂ η_g₂ : Mor₂Iso) (ih_η ih_θ : Expr) : m Expr + /-- The naturality for the inverse. -/ + mkNaturalityInv (p pf : NormalizedHom) (f g : Mor₁) (η η_f η_g : Mor₂Iso) (ih_η : Expr) : m Expr + +open MonadNormalizeNaturality + +variable [MonadCoherehnceHom (CoherenceM ρ)] [MonadNormalizeNaturality (CoherenceM ρ)] + +/-- Meta version of `CategoryTheory.FreeBicategory.normalize_naturality`. -/ +partial def naturality (nm : Name) (p : NormalizedHom) (η : Mor₂Iso) : CoherenceM ρ Expr := do + let result ← match η with + | .of _ => throwError m!"could not find a structural isomorphism, but {η.e}" + | .coherenceComp _ _ _ _ _ α η θ => withTraceNode nm (fun _ => return m!"monoidalComp") do + let α ← MonadCoherehnceHom.unfoldM α + let αθ ← comp₂M α θ + let ηαθ ← comp₂M η αθ + naturality nm p ηαθ + | .structuralAtom η => match η with + | .coherenceHom α => withTraceNode nm (fun _ => return m!"coherenceHom") do + let α ← MonadCoherehnceHom.unfoldM α + naturality nm p α + | .associator _ f g h => withTraceNode nm (fun _ => return m!"associator") do + let ⟨pf, η_f⟩ ← normalize p f + let ⟨pfg, η_g⟩ ← normalize pf g + let ⟨pfgh, η_h⟩ ← normalize pfg h + mkNaturalityAssociator p pf pfg pfgh f g h η_f η_g η_h + | .leftUnitor _ f => withTraceNode nm (fun _ => return m!"leftUnitor") do + let ⟨pf, η_f⟩ ← normalize p f + mkNaturalityLeftUnitor p pf f η_f + | .rightUnitor _ f => withTraceNode nm (fun _ => return m!"rightUnitor") do + let ⟨pf, η_f⟩ ← normalize p f + mkNaturalityRightUnitor p pf f η_f + | .id _ f => withTraceNode nm (fun _ => return m!"id") do + let ⟨pf, η_f⟩ ← normalize p f + mkNaturalityId p pf f η_f + | .comp _ f g h η θ => withTraceNode nm (fun _ => return m!"comp") do + let ⟨pf, η_f⟩ ← normalize p f + let ⟨_, η_g⟩ ← normalize p g + let ⟨_, η_h⟩ ← normalize p h + let ih_η ← naturality nm p η + let ih_θ ← naturality nm p θ + mkNaturalityComp p pf f g h η θ η_f η_g η_h ih_η ih_θ + | .whiskerLeft _ f g h η => withTraceNode nm (fun _ => return m!"whiskerLeft") do + let ⟨pf, η_f⟩ ← normalize p f + let ⟨pfg, η_fg⟩ ← normalize pf g + let ⟨_, η_fh⟩ ← normalize pf h + let ih ← naturality nm pf η + mkNaturalityWhiskerLeft p pf pfg f g h η η_f η_fg η_fh ih + | .whiskerRight _ f g η h => withTraceNode nm (fun _ => return m!"whiskerRight") do + let ⟨pf, η_f⟩ ← normalize p f + let ⟨_, η_g⟩ ← normalize p g + let ⟨pfh, η_fh⟩ ← normalize pf h + let ih ← naturality nm p η + mkNaturalityWhiskerRight p pf pfh f g h η η_f η_g η_fh ih + | .horizontalComp _ f₁ g₁ f₂ g₂ η θ => withTraceNode nm (fun _ => return m!"hComp") do + let ⟨pf₁, η_f₁⟩ ← normalize p f₁ + let ⟨_, η_g₁⟩ ← normalize p g₁ + let ⟨pf₁f₂, η_f₂⟩ ← normalize pf₁ f₂ + let ⟨_, η_g₂⟩ ← normalize pf₁ g₂ + let ih_η ← naturality nm p η + let ih_θ ← naturality nm pf₁ θ + mkNaturalityHorizontalComp p pf₁ pf₁f₂ f₁ g₁ f₂ g₂ η θ η_f₁ η_g₁ η_f₂ η_g₂ ih_η ih_θ + | .inv _ f g η => withTraceNode nm (fun _ => return m!"inv") do + let ⟨pf, η_f⟩ ← normalize p f + let ⟨_, η_g⟩ ← normalize p g + let ih_η ← naturality nm p η + mkNaturalityInv p pf f g η η_f η_g ih_η + withTraceNode nm (fun _ => return m!"{checkEmoji} {← inferType result}") do + if ← isTracingEnabledFor nm then addTrace nm m!"proof: {result}" + return result + +/-- Prove the equality between structural isomorphisms using the naturality of `normalize`. -/ +class MkEqOfNaturality (m : Type → Type) where + /-- Auxiliary function for `pureCoherence`. -/ + mkEqOfNaturality (η θ : Expr) (η' θ' : IsoLift) (η_f η_g : Mor₂Iso) (Hη Hθ : Expr) : m Expr + +export MkEqOfNaturality (mkEqOfNaturality) + +/-- Close the goal of the form `η = θ`, where `η` and `θ` are 2-isomorphisms made up only of +associators, unitors, and identities. -/ +def pureCoherence (ρ : Type) [Context ρ] [MkMor₂ (CoherenceM ρ)] + [MonadMor₁ (CoherenceM ρ)] [MonadMor₂Iso (CoherenceM ρ)] + [MonadCoherehnceHom (CoherenceM ρ)] [MonadNormalizeNaturality (CoherenceM ρ)] + [MkEqOfNaturality (CoherenceM ρ)] + (nm : Name) (mvarId : MVarId) : MetaM (List MVarId) := + mvarId.withContext do + withTraceNode nm (fun ex => match ex with + | .ok _ => return m!"{checkEmoji} coherence equality: {← mvarId.getType}" + | .error err => return m!"{crossEmoji} {err.toMessageData}") do + let e ← instantiateMVars <| ← mvarId.getType + let some (_, η, θ) := (← whnfR e).eq? + | throwError "coherence requires an equality goal" + let ctx : ρ ← mkContext η + CoherenceM.run (ctx := ctx) do + let .some ηIso := (← MkMor₂.ofExpr η).isoLift? | + throwError "could not find a structural isomorphism, but {η}" + let .some θIso := (← MkMor₂.ofExpr θ).isoLift? | + throwError "could not find a structural isomorphism, but {θ}" + let f ← ηIso.e.srcM + let g ← ηIso.e.tgtM + let a := f.src + let nil ← normalizedHom.nilM a + let ⟨_, η_f⟩ ← normalize nil f + let ⟨_, η_g⟩ ← normalize nil g + let Hη ← withTraceNode nm (fun ex => do return m!"{exceptEmoji ex} LHS") do + naturality nm nil ηIso.e + let Hθ ← withTraceNode nm (fun ex => do return m!"{exceptEmoji ex} RHS") do + naturality nm nil θIso.e + let H ← mkEqOfNaturality η θ ηIso θIso η_f η_g Hη Hθ + mvarId.apply H + +end Mathlib.Tactic.BicategoryLike diff --git a/Mathlib/Tactic/CategoryTheory/Monoidal.lean b/Mathlib/Tactic/CategoryTheory/Monoidal.lean deleted file mode 100644 index 5c2b2f1b99eda..0000000000000 --- a/Mathlib/Tactic/CategoryTheory/Monoidal.lean +++ /dev/null @@ -1,684 +0,0 @@ -/- -Copyright (c) 2024 Yuma Mizuno. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yuma Mizuno --/ -import Mathlib.Tactic.CategoryTheory.MonoidalComp - -/-! -# Normalization of morphisms in monoidal categories -This file provides a tactic that normalizes morphisms in monoidal categories. This is used in the -string diagram widget given in `Mathlib.Tactic.StringDiagram`. -We say that the morphism `η` in a monoidal category is in normal form if -1. `η` is of the form `α₀ ≫ η₀ ≫ α₁ ≫ η₁ ≫ ... αₘ ≫ ηₘ ≫ αₘ₊₁` where each `αᵢ` is a - structural 2-morphism (consisting of associators and unitors), -2. each `ηᵢ` is a non-structural 2-morphism of the form `f₁ ◁ ... ◁ fₘ ◁ θ`, and -3. `θ` is of the form `ι ▷ g₁ ▷ ... ▷ gₗ` - -Note that the structural morphisms `αᵢ` are not necessarily normalized, as the main purpose -is to get a list of the non-structural morphisms out. - -Currently, the primary application of the normalization tactic in mind is drawing string diagrams, -which are graphical representations of morphisms in monoidal categories, in the infoview. When -drawing string diagrams, we often ignore associators and unitors (i.e., drawing morphisms in -strict monoidal categories). On the other hand, in Lean, it is considered difficult to formalize -the concept of strict monoidal categories due to the feature of dependent type theory. The -normalization tactic can remove associators and unitors from the expression, extracting the -necessary data for drawing string diagrams. - -The current plan on drawing string diagrams (#10581) is to use -Penrose (https://github.com/penrose) via ProofWidget. However, it should be noted that the -normalization procedure in this file does not rely on specific settings, allowing for broader -application. - -Future plans include the following. At least I (Yuma) would like to work on these in the future, -but it might not be immediate. If anyone is interested, I would be happy to discuss. - -- Currently (#10581), the string diagrams only do drawing. It would be better they also generate - proofs. That is, by manipulating the string diagrams displayed in the infoview with a mouse to - generate proofs. In #10581, the string diagram widget only uses the morphisms generated by the - normalization tactic and does not use proof terms ensuring that the original morphism and the - normalized morphism are equal. Proof terms will be necessary for proof generation. - -- There is also the possibility of using homotopy.io (https://github.com/homotopy-io), a graphical - proof assistant for category theory, from Lean. At this point, I have very few ideas regarding - this approach. - -- The normalization tactic allows for an alternative implementation of the coherent tactic. - -## Main definitions -- `Tactic.Monoidal.eval`: Given a Lean expression `e` that represents a morphism in a monoidal -category, this function returns a pair of `⟨e', pf⟩` where `e'` is the normalized expression of `e` -and `pf` is a proof that `e = e'`. - --/ - -open Lean Meta Elab -open CategoryTheory - -namespace Mathlib.Tactic.Monoidal - -/-- The context for evaluating expressions. -/ -structure Context where - /-- The expression for the underlying category. -/ - C : Expr - -/-- Populate a `context` object for evaluating `e`. -/ -def mkContext? (e : Expr) : MetaM (Option Context) := do - match (← inferType e).getAppFnArgs with - | (``Quiver.Hom, #[_, _, f, _]) => - let C ← inferType f - return some ⟨C⟩ - | _ => return none - -/-- The monad for the normalization of 2-morphisms. -/ -abbrev MonoidalM := ReaderT Context MetaM - -/-- Run a computation in the `M` monad. -/ -abbrev MonoidalM.run {α : Type} (c : Context) (m : MonoidalM α) : MetaM α := - ReaderT.run m c - -/-- Expressions for atomic 1-morphisms. -/ -structure Atom₁ : Type where - /-- Extract a Lean expression from an `Atom₁` expression. -/ - e : Expr - -/-- Expressions for 1-morphisms. -/ -inductive Mor₁ : Type - /-- `id` is the expression for `𝟙_ C`. -/ - | id : Mor₁ - /-- `comp X Y` is the expression for `X ⊗ Y` -/ - | comp : Mor₁ → Mor₁ → Mor₁ - /-- Construct the expression for an atomic 1-morphism. -/ - | of : Atom₁ → Mor₁ - deriving Inhabited - -/-- Converts a 1-morphism into a list of its components. -/ -def Mor₁.toList : Mor₁ → List Atom₁ - | .id => [] - | .comp f g => f.toList ++ g.toList - | .of f => [f] - -/-- Returns `𝟙_ C` if the expression `e` is of the form `𝟙_ C`. -/ -def isTensorUnit? (e : Expr) : MetaM (Option Expr) := do - let C ← mkFreshExprMVar none - let instC ← mkFreshExprMVar none - let instMC ← mkFreshExprMVar none - let unit := mkAppN (← mkConstWithFreshMVarLevels - ``MonoidalCategoryStruct.tensorUnit) #[C, instC, instMC] - if ← withDefault <| isDefEq e unit then - return ← instantiateMVars unit - else - return none - -/-- Returns `(f, g)` if the expression `e` is of the form `f ⊗ g`. -/ -def isTensorObj? (e : Expr) : MetaM (Option (Expr × Expr)) := do - let C ← mkFreshExprMVar none - let f ← mkFreshExprMVar C - let g ← mkFreshExprMVar C - let instC ← mkFreshExprMVar none - let instMC ← mkFreshExprMVar none - let fg := mkAppN (← mkConstWithFreshMVarLevels - ``MonoidalCategoryStruct.tensorObj) #[C, instC, instMC, f, g] - if ← withDefault <| isDefEq e fg then - return (← instantiateMVars f, ← instantiateMVars g) - else - return none - -/-- Construct a `Mor₁` expression from a Lean expression. -/ -partial def toMor₁ (e : Expr) : MetaM Mor₁ := do - if let some _ ← isTensorUnit? e then - return Mor₁.id - else if let some (f, g) ← isTensorObj? e then - return (← toMor₁ f).comp (← toMor₁ g) - else - return Mor₁.of ⟨e⟩ - -/-- Expressions for atomic structural 2-morphisms. -/ -inductive StructuralAtom : Type - /-- The expression for the associator `(α_ f g h).hom`. -/ - | associator (f g h : Mor₁) : StructuralAtom - /-- The expression for the inverse of the associator `(α_ f g h).inv`. -/ - | associatorInv (f g h : Mor₁) : StructuralAtom - /-- The expression for the left unitor `(λ_ f).hom`. -/ - | leftUnitor (f : Mor₁) : StructuralAtom - /-- The expression for the inverse of the left unitor `(λ_ f).inv`. -/ - | leftUnitorInv (f : Mor₁) : StructuralAtom - /-- The expression for the right unitor `(ρ_ f).hom`. -/ - | rightUnitor (f : Mor₁) : StructuralAtom - /-- The expression for the inverse of the right unitor `(ρ_ f).inv`. -/ - | rightUnitorInv (f : Mor₁) : StructuralAtom - /-- Expressions for `α` in the monoidal composition `η ⊗≫ θ := η ≫ α ≫ θ`. -/ - | monoidalCoherence (f g : Mor₁) (e : Expr) : StructuralAtom - deriving Inhabited - -/-- Construct a `StructuralAtom` expression from a Lean expression. -/ -def structuralAtom? (e : Expr) : MetaM (Option StructuralAtom) := do - match ← whnfR e with - -- whnfR version of `Iso.hom η` - | .proj ``Iso 0 η => - match (← whnfR η).getAppFnArgs with - | (``MonoidalCategoryStruct.associator, #[_, _, _, f, g, h]) => - return some <| .associator (← toMor₁ f) (← toMor₁ g) (← toMor₁ h) - | (``MonoidalCategoryStruct.leftUnitor, #[_, _, _, f]) => - return some <| .leftUnitor (← toMor₁ f) - | (``MonoidalCategoryStruct.rightUnitor, #[_, _, _, f]) => - return some <| .rightUnitor (← toMor₁ f) - | (``MonoidalCoherence.iso, #[_, _, f, g, inst]) => - return some <| .monoidalCoherence (← toMor₁ f) (← toMor₁ g) inst - | _ => return none - -- whnfR version of `Iso.inv η` - | .proj ``Iso 1 η => - match (← whnfR η).getAppFnArgs with - | (``MonoidalCategoryStruct.associator, #[_, _, _, f, g, h]) => - return some <| .associatorInv (← toMor₁ f) (← toMor₁ g) (← toMor₁ h) - | (``MonoidalCategoryStruct.leftUnitor, #[_, _, _, f]) => - return some <| .leftUnitorInv (← toMor₁ f) - | (``MonoidalCategoryStruct.rightUnitor, #[_, _, _, f]) => - return some <| .rightUnitorInv (← toMor₁ f) - | _ => return none - | _ => return none - -/-- Expressions for atomic non-structural 2-morphisms. -/ -structure Atom where - /-- Extract a Lean expression from an `Atom` expression. -/ - e : Expr - deriving Inhabited - -/-- Expressions of the form `η ▷ f₁ ▷ ... ▷ fₙ`. -/ -inductive WhiskerRightExpr : Type - /-- Construct the expression for an atomic 2-morphism. -/ - | of (η : Atom) : WhiskerRightExpr - /-- Construct the expression for `η ▷ f`. -/ - | whisker (η : WhiskerRightExpr) (f : Atom₁) : WhiskerRightExpr - deriving Inhabited - -/-- Expressions of the form `f₁ ◁ ... ◁ fₙ ◁ η`. -/ -inductive WhiskerLeftExpr : Type - /-- Construct the expression for a right-whiskered 2-morphism. -/ - | of (η : WhiskerRightExpr) : WhiskerLeftExpr - /-- Construct the expression for `f ◁ η`. -/ - | whisker (f : Atom₁) (η : WhiskerLeftExpr) : WhiskerLeftExpr - deriving Inhabited - -/-- Expressions for structural 2-morphisms. -/ -inductive Structural : Type - /-- Expressions for atomic structural 2-morphisms. -/ - | atom (η : StructuralAtom) : Structural - /-- Expressions for the identity `𝟙 f`. -/ - | id (f : Mor₁) : Structural - /-- Expressions for the composition `η ≫ θ`. -/ - | comp (α β : Structural) : Structural - /-- Expressions for the left whiskering `f ◁ η`. -/ - | whiskerLeft (f : Mor₁) (η : Structural) : Structural - /-- Expressions for the right whiskering `η ▷ f`. -/ - | whiskerRight (η : Structural) (f : Mor₁) : Structural - deriving Inhabited - -/-- Normalized expressions for 2-morphisms. -/ -inductive NormalExpr : Type - /-- Construct the expression for a structural 2-morphism. -/ - | nil (α : Structural) : NormalExpr - /-- Construct the normalized expression of 2-morphisms recursively. -/ - | cons (head_structural : Structural) (head : WhiskerLeftExpr) (tail : NormalExpr) : NormalExpr - deriving Inhabited - -/-- The domain of a morphism. -/ -def src (η : Expr) : MetaM Mor₁ := do - match (← inferType η).getAppFnArgs with - | (``Quiver.Hom, #[_, _, f, _]) => toMor₁ f - | _ => throwError "{η} is not a morphism" - -/-- The codomain of a morphism. -/ -def tgt (η : Expr) : MetaM Mor₁ := do - match (← inferType η).getAppFnArgs with - | (``Quiver.Hom, #[_, _, _, g]) => toMor₁ g - | _ => throwError "{η} is not a morphism" - -/-- The domain of a 2-morphism. -/ -def Atom.src (η : Atom) : MetaM Mor₁ := do Monoidal.src η.e - -/-- The codomain of a 2-morphism. -/ -def Atom.tgt (η : Atom) : MetaM Mor₁ := do Monoidal.tgt η.e - -/-- The domain of a 2-morphism. -/ -def WhiskerRightExpr.src : WhiskerRightExpr → MetaM Mor₁ - | WhiskerRightExpr.of η => η.src - | WhiskerRightExpr.whisker η f => return (← WhiskerRightExpr.src η).comp (Mor₁.of f) - -/-- The codomain of a 2-morphism. -/ -def WhiskerRightExpr.tgt : WhiskerRightExpr → MetaM Mor₁ - | WhiskerRightExpr.of η => η.tgt - | WhiskerRightExpr.whisker η f => return (← WhiskerRightExpr.tgt η).comp (Mor₁.of f) - -/-- The domain of a 2-morphism. -/ -def WhiskerLeftExpr.src : WhiskerLeftExpr → MetaM Mor₁ - | WhiskerLeftExpr.of η => WhiskerRightExpr.src η - | WhiskerLeftExpr.whisker f η => return (Mor₁.of f).comp (← WhiskerLeftExpr.src η) - -/-- The codomain of a 2-morphism. -/ -def WhiskerLeftExpr.tgt : WhiskerLeftExpr → MetaM Mor₁ - | WhiskerLeftExpr.of η => WhiskerRightExpr.tgt η - | WhiskerLeftExpr.whisker f η => return (Mor₁.of f).comp (← WhiskerLeftExpr.tgt η) - -/-- The domain of a 2-morphism. -/ -def StructuralAtom.src : StructuralAtom → Mor₁ - | .associator f g h => (f.comp g).comp h - | .associatorInv f g h => f.comp (g.comp h) - | .leftUnitor f => Mor₁.id.comp f - | .leftUnitorInv f => f - | .rightUnitor f => f.comp Mor₁.id - | .rightUnitorInv f => f - | .monoidalCoherence f _ _ => f - -/-- The codomain of a 2-morphism. -/ -def StructuralAtom.tgt : StructuralAtom → Mor₁ - | .associator f g h => f.comp (g.comp h) - | .associatorInv f g h => (f.comp g).comp h - | .leftUnitor f => f - | .leftUnitorInv f => Mor₁.id.comp f - | .rightUnitor f => f - | .rightUnitorInv f => f.comp Mor₁.id - | .monoidalCoherence _ g _ => g - -/-- The domain of a 2-morphism. -/ -def Structural.src : Structural → Mor₁ - | .atom η => η.src - | .id f => f - | .comp α _ => α.src - | .whiskerLeft f η => f.comp η.src - | .whiskerRight η f => η.src.comp f - -/-- The codomain of a 2-morphism. -/ -def Structural.tgt : Structural → Mor₁ - | .atom η => η.tgt - | .id f => f - | .comp _ β => β.tgt - | .whiskerLeft f η => f.comp η.tgt - | .whiskerRight η f => η.tgt.comp f - -/-- The domain of a 2-morphism. -/ -def NormalExpr.src : NormalExpr → Mor₁ - | NormalExpr.nil η => η.src - | NormalExpr.cons α _ _ => α.src - -/-- The codomain of a 2-morphism. -/ -def NormalExpr.tgt : NormalExpr → Mor₁ - | NormalExpr.nil η => η.tgt - | NormalExpr.cons _ _ ηs => ηs.tgt - -/-- The associator as a term of `normalExpr`. -/ -def NormalExpr.associator (f g h : Mor₁) : NormalExpr := - .nil <| .atom <| .associator f g h - -/-- The inverse of the associator as a term of `normalExpr`. -/ -def NormalExpr.associatorInv (f g h : Mor₁) : NormalExpr := - .nil <| .atom <| .associatorInv f g h - -/-- The left unitor as a term of `normalExpr`. -/ -def NormalExpr.leftUnitor (f : Mor₁) : NormalExpr := - .nil <| .atom <| .leftUnitor f - -/-- The inverse of the left unitor as a term of `normalExpr`. -/ -def NormalExpr.leftUnitorInv (f : Mor₁) : NormalExpr := - .nil <| .atom <| .leftUnitorInv f - -/-- The right unitor as a term of `normalExpr`. -/ -def NormalExpr.rightUnitor (f : Mor₁) : NormalExpr := - .nil <| .atom <| .rightUnitor f - -/-- The inverse of the right unitor as a term of `normalExpr`. -/ -def NormalExpr.rightUnitorInv (f : Mor₁) : NormalExpr := - .nil <| .atom <| .rightUnitorInv f - -/-- Construct a `NormalExpr` expression from a `WhiskerLeftExpr` expression. -/ -def NormalExpr.of (η : WhiskerLeftExpr) : MetaM NormalExpr := do - return .cons (.id (← η.src)) η (.nil (.id (← η.tgt))) - -/-- Construct a `NormalExpr` expression from a Lean expression for an atomic 2-morphism. -/ -def NormalExpr.ofExpr (η : Expr) : MetaM NormalExpr := - NormalExpr.of <| .of <| .of ⟨η⟩ - -/-- If `e` is an expression of the form `η ⊗≫ θ := η ≫ α ≫ θ` in the monoidal category `C`, -return the expression for `α` .-/ -def structuralOfMonoidalComp (C e : Expr) : MetaM Structural := do - let v ← mkFreshLevelMVar - let u ← mkFreshLevelMVar - _ ← isDefEq (.sort (.succ v)) (← inferType (← inferType e)) - _ ← isDefEq (.sort (.succ u)) (← inferType C) - let W ← mkFreshExprMVar none - let X ← mkFreshExprMVar none - let Y ← mkFreshExprMVar none - let Z ← mkFreshExprMVar none - let f ← mkFreshExprMVar none - let g ← mkFreshExprMVar none - let α₀ ← mkFreshExprMVar none - let instC ← mkFreshExprMVar none - let αg := mkAppN (.const ``CategoryStruct.comp [v, u]) #[C, instC, X, Y, Z, α₀, g] - let fαg := mkAppN (.const ``CategoryStruct.comp [v, u]) #[C, instC, W, X, Z, f, αg] - _ ← isDefEq e fαg - match ← structuralAtom? α₀ with - | some η => return .atom η - | none => throwError "not a structural 2-morphism" - -section - -open scoped MonoidalCategory - -universe v u - -variable {C : Type u} [Category.{v} C] - -variable {f f' g g' h i j : C} - -theorem evalComp_nil_cons {f g h i j : C} (α : f ⟶ g) (β : g ⟶ h) (η : h ⟶ i) (ηs : i ⟶ j) : - α ≫ (β ≫ η ≫ ηs) = (α ≫ β) ≫ η ≫ ηs := by - simp - -@[nolint synTaut] -theorem evalComp_nil_nil {f g h : C} (α : f ⟶ g) (β : g ⟶ h) : - α ≫ β = α ≫ β := by - simp - -theorem evalComp_cons {f g h i j : C} (α : f ⟶ g) (η : g ⟶ h) {ηs : h ⟶ i} {θ : i ⟶ j} {ι : h ⟶ j} - (pf_ι : ηs ≫ θ = ι) : - (α ≫ η ≫ ηs) ≫ θ = α ≫ η ≫ ι := by - simp [pf_ι] - -theorem eval_comp - {η η' : f ⟶ g} {θ θ' : g ⟶ h} {ι : f ⟶ h} - (pf_η : η = η') (pf_θ : θ = θ') (pf_ηθ : η' ≫ θ' = ι) : - η ≫ θ = ι := by - simp [pf_η, pf_θ, pf_ηθ] - -theorem eval_of (η : f ⟶ g) : - η = 𝟙 _ ≫ η ≫ 𝟙 _ := by - simp - -theorem eval_monoidalComp - {η η' : f ⟶ g} {α : g ⟶ h} {θ θ' : h ⟶ i} {αθ : g ⟶ i} {ηαθ : f ⟶ i} - (pf_η : η = η') (pf_θ : θ = θ') (pf_αθ : α ≫ θ' = αθ) (pf_ηαθ : η' ≫ αθ = ηαθ) : - η ≫ α ≫ θ = ηαθ := by - simp [pf_η, pf_θ, pf_αθ, pf_ηαθ] - -variable [MonoidalCategory C] - -@[nolint synTaut] -theorem evalWhiskerLeft_nil (f : C) (α : g ⟶ h) : - f ◁ α = f ◁ α := by - simp - -theorem evalWhiskerLeft_of_cons - (α : g ⟶ h) (η : h ⟶ i) {ηs : i ⟶ j} {θ : f ⊗ i ⟶ f ⊗ j} (pf_θ : f ◁ ηs = θ) : - f ◁ (α ≫ η ≫ ηs) = f ◁ α ≫ f ◁ η ≫ θ := by - simp [pf_θ] - -theorem evalWhiskerLeft_comp {η : h ⟶ i} {θ : g ⊗ h ⟶ g ⊗ i} {ι : f ⊗ g ⊗ h ⟶ f ⊗ g ⊗ i} - {ι' : f ⊗ g ⊗ h ⟶ (f ⊗ g) ⊗ i} {ι'' : (f ⊗ g) ⊗ h ⟶ (f ⊗ g) ⊗ i} - (pf_θ : g ◁ η = θ) (pf_ι : f ◁ θ = ι) - (pf_ι' : ι ≫ (α_ _ _ _).inv = ι') (pf_ι'' : (α_ _ _ _).hom ≫ ι' = ι'') : - (f ⊗ g) ◁ η = ι'' := by - simp [pf_θ, pf_ι, pf_ι', pf_ι''] - -theorem evalWhiskerLeft_id {f g : C} {η : f ⟶ g} - {η' : f ⟶ 𝟙_ C ⊗ g} {η'' : 𝟙_ C ⊗ f ⟶ 𝟙_ C ⊗ g} - (pf_η' : η ≫ (λ_ _).inv = η') (pf_η'' : (λ_ _).hom ≫ η' = η'') : - 𝟙_ C ◁ η = η'' := by - simp [pf_η', pf_η''] - -theorem eval_whiskerLeft - {η η' : g ⟶ h} {θ : f ⊗ g ⟶ f ⊗ h} - (pf_η : η = η') (pf_θ : f ◁ η' = θ) : - f ◁ η = θ := by - simp [pf_η, pf_θ] - -theorem eval_whiskerRight - {η η' : f ⟶ g} {θ : f ⊗ h ⟶ g ⊗ h} - (pf_η : η = η') (pf_θ : η' ▷ h = θ) : - η ▷ h = θ := by - simp [pf_η, pf_θ] - -@[nolint synTaut] -theorem evalWhiskerRight_nil (α : f ⟶ g) (h : C) : - α ▷ h = α ▷ h := by - simp - -theorem evalWhiskerRight_cons_of_of - (α : f ⟶ g) (η : g ⟶ h) {ηs : h ⟶ i} {θ : h ⊗ j ⟶ i ⊗ j} - (pf_θ : ηs ▷ j = θ) : - (α ≫ η ≫ ηs) ▷ j = α ▷ j ≫ η ▷ j ≫ θ := by - simp [pf_θ] - -theorem evalWhiskerRight_cons_whisker - {α : g ⟶ f ⊗ h} {η : h ⟶ i} {ηs : f ⊗ i ⟶ j} {k : C} - {η₁ : h ⊗ k ⟶ i ⊗ k} {η₂ : f ⊗ (h ⊗ k) ⟶ f ⊗ (i ⊗ k)} {ηs₁ : (f ⊗ i) ⊗ k ⟶ j ⊗ k} - {ηs₂ : f ⊗ (i ⊗ k) ⟶ j ⊗ k} {η₃ : f ⊗ (h ⊗ k) ⟶ j ⊗ k} {η₄ : (f ⊗ h) ⊗ k ⟶ j ⊗ k} - {η₅ : g ⊗ k ⟶ j ⊗ k} - (pf_η₁ : (𝟙 _ ≫ η ≫ 𝟙 _ ) ▷ k = η₁) (pf_η₂ : f ◁ η₁ = η₂) - (pf_ηs₁ : ηs ▷ k = ηs₁) (pf_ηs₂ : (α_ _ _ _).inv ≫ ηs₁ = ηs₂) - (pf_η₃ : η₂ ≫ ηs₂ = η₃) (pf_η₄ : (α_ _ _ _).hom ≫ η₃ = η₄) (pf_η₅ : α ▷ k ≫ η₄ = η₅) : - (α ≫ (f ◁ η) ≫ ηs) ▷ k = η₅ := by - simp at pf_η₁ - simp [pf_η₁, pf_η₂, pf_ηs₁, pf_ηs₂, pf_η₃, pf_η₄, pf_η₅] - -theorem evalWhiskerRight_comp - {η : f ⟶ f'} {η₁ : f ⊗ g ⟶ f' ⊗ g} {η₂ : (f ⊗ g) ⊗ h ⟶ (f' ⊗ g) ⊗ h} - {η₃ : (f ⊗ g) ⊗ h ⟶ f' ⊗ (g ⊗ h)} {η₄ : f ⊗ (g ⊗ h) ⟶ f' ⊗ (g ⊗ h)} - (pf_η₁ : η ▷ g = η₁) (pf_η₂ : η₁ ▷ h = η₂) - (pf_η₃ : η₂ ≫ (α_ _ _ _).hom = η₃) (pf_η₄ : (α_ _ _ _).inv ≫ η₃ = η₄) : - η ▷ (g ⊗ h) = η₄ := by - simp [pf_η₁, pf_η₂, pf_η₃, pf_η₄] - -theorem evalWhiskerRight_id - {η : f ⟶ g} {η₁ : f ⟶ g ⊗ 𝟙_ C} {η₂ : f ⊗ 𝟙_ C ⟶ g ⊗ 𝟙_ C} - (pf_η₁ : η ≫ (ρ_ _).inv = η₁) (pf_η₂ : (ρ_ _).hom ≫ η₁ = η₂) : - η ▷ 𝟙_ C = η₂ := by - simp [pf_η₁, pf_η₂] - -end - -/-- Extract a Lean expression from a `Mor₁` expression. -/ -def Mor₁.e : Mor₁ → MonoidalM Expr - | .id => do - let ctx ← read - mkAppOptM ``MonoidalCategoryStruct.tensorUnit #[ctx.C, none, none] - | .comp f g => do - mkAppM ``MonoidalCategoryStruct.tensorObj #[← Mor₁.e f, ← Mor₁.e g] - | .of f => return f.e - -/-- Extract a Lean expression from a `StructuralAtom` expression. -/ -def StructuralAtom.e : StructuralAtom → MonoidalM Expr - | .associator f g h => do - mkAppM ``Iso.hom #[← mkAppM ``MonoidalCategoryStruct.associator #[← f.e, ← g.e, ← h.e]] - | .associatorInv f g h => do - mkAppM ``Iso.inv #[← mkAppM ``MonoidalCategoryStruct.associator #[← f.e, ← g.e, ← h.e]] - | .leftUnitor f => do - mkAppM ``Iso.hom #[← mkAppM ``MonoidalCategoryStruct.leftUnitor #[← f.e]] - | .leftUnitorInv f => do - mkAppM ``Iso.inv #[← mkAppM ``MonoidalCategoryStruct.leftUnitor #[← f.e]] - | .rightUnitor f => do - mkAppM ``Iso.hom #[← mkAppM ``MonoidalCategoryStruct.rightUnitor #[← f.e]] - | .rightUnitorInv f => do - mkAppM ``Iso.inv #[← mkAppM ``MonoidalCategoryStruct.rightUnitor #[← f.e]] - | .monoidalCoherence _ _ e => do - mkAppM ``Iso.hom #[← mkAppOptM ``MonoidalCoherence.iso #[none, none, none, none, e]] - -/-- Extract a Lean expression from a `Structural` expression. -/ -partial def Structural.e : Structural → MonoidalM Expr - | .atom η => η.e - | .id f => do mkAppM ``CategoryStruct.id #[← f.e] - | .comp α β => do mkAppM ``CategoryStruct.comp #[← α.e, ← β.e] - | .whiskerLeft f η => do mkAppM ``MonoidalCategoryStruct.whiskerLeft #[← f.e, ← η.e] - | .whiskerRight η f => do mkAppM ``MonoidalCategoryStruct.whiskerRight #[← η.e, ← f.e] - -/-- Extract a Lean expression from a `WhiskerRightExpr` expression. -/ -def WhiskerRightExpr.e : WhiskerRightExpr → MonoidalM Expr - | WhiskerRightExpr.of η => return η.e - | WhiskerRightExpr.whisker η f => do - mkAppM ``MonoidalCategoryStruct.whiskerRight #[← η.e, f.e] - -/-- Extract a Lean expression from a `WhiskerLeftExpr` expression. -/ -def WhiskerLeftExpr.e : WhiskerLeftExpr → MonoidalM Expr - | WhiskerLeftExpr.of η => η.e - | WhiskerLeftExpr.whisker f η => do - mkAppM ``MonoidalCategoryStruct.whiskerLeft #[f.e, ← η.e] - -/-- Extract a Lean expression from a `NormalExpr` expression. -/ -def NormalExpr.e : NormalExpr → MonoidalM Expr - | NormalExpr.nil α => α.e - | NormalExpr.cons α η θ => do - mkAppM ``CategoryStruct.comp #[← α.e, ← mkAppM ``CategoryStruct.comp #[← η.e, ← θ.e]] - -/-- The result of evaluating an expression into normal form. -/ -structure Result where - /-- The normalized expression of the 2-morphism. -/ - expr : NormalExpr - /-- The proof that the normalized expression is equal to the original expression. -/ - proof : Expr - -/-- Evaluate the expression `η ≫ θ` into a normalized form. -/ -partial def evalComp : NormalExpr → NormalExpr → MonoidalM Result - | .nil α, .cons β η ηs => do - let η' := .cons (α.comp β) η ηs - return ⟨η', ← mkAppM ``evalComp_nil_cons #[← α.e, ← β.e, ← η.e, ← ηs.e]⟩ - | .nil α, .nil α' => do - return ⟨.nil (α.comp α'), ← mkAppM ``evalComp_nil_nil #[← α.e, ← α'.e]⟩ - | .cons α η ηs, θ => do - let ⟨ι, pf_ι⟩ ← evalComp ηs θ - let ι' := .cons α η ι - return ⟨ι', ← mkAppM ``evalComp_cons #[← α.e, ← η.e, pf_ι]⟩ - -/-- Evaluate the expression `f ◁ η` into a normalized form. -/ -partial def evalWhiskerLeftExpr : Mor₁ → NormalExpr → MonoidalM Result - | f, .nil α => do - return ⟨.nil (.whiskerLeft f α), ← mkAppM ``evalWhiskerLeft_nil #[← f.e, ← α.e]⟩ - | .of f, .cons α η ηs => do - let η' := WhiskerLeftExpr.whisker f η - let ⟨θ, pf_θ⟩ ← evalWhiskerLeftExpr (.of f) ηs - let η'' := .cons (.whiskerLeft (.of f) α) η' θ - return ⟨η'', ← mkAppM ``evalWhiskerLeft_of_cons #[← α.e, ← η.e, pf_θ]⟩ - | .comp f g, η => do - let ⟨θ, pf_θ⟩ ← evalWhiskerLeftExpr g η - let ⟨ι, pf_ι⟩ ← evalWhiskerLeftExpr f θ - let h := η.src - let h' := η.tgt - let ⟨ι', pf_ι'⟩ ← evalComp ι (NormalExpr.associatorInv f g h') - let ⟨ι'', pf_ι''⟩ ← evalComp (NormalExpr.associator f g h) ι' - return ⟨ι'', ← mkAppM ``evalWhiskerLeft_comp #[pf_θ, pf_ι, pf_ι', pf_ι'']⟩ - | .id, η => do - let f := η.src - let g := η.tgt - let ⟨η', pf_η'⟩ ← evalComp η (NormalExpr.leftUnitorInv g) - let ⟨η'', pf_η''⟩ ← evalComp (NormalExpr.leftUnitor f) η' - return ⟨η'', ← mkAppM ``evalWhiskerLeft_id #[pf_η', pf_η'']⟩ - -/-- Evaluate the expression `η ▷ f` into a normalized form. -/ -partial def evalWhiskerRightExpr : NormalExpr → Mor₁ → MonoidalM Result - | .nil α, h => do - return ⟨.nil (.whiskerRight α h), ← mkAppM ``evalWhiskerRight_nil #[← α.e, ← h.e]⟩ - | .cons α (.of η) ηs, .of f => do - let ⟨θ, pf_θ⟩ ← evalWhiskerRightExpr ηs (.of f) - let η' := .cons (.whiskerRight α (.of f)) (.of (.whisker η f)) θ - return ⟨η', ← mkAppM ``evalWhiskerRight_cons_of_of #[← α.e, ← η.e, pf_θ]⟩ - | .cons α (.whisker f η) ηs, h => do - let g ← η.src - let g' ← η.tgt - let ⟨η₁, pf_η₁⟩ ← evalWhiskerRightExpr (.cons (.id g) η (.nil (.id g'))) h - let ⟨η₂, pf_η₂⟩ ← evalWhiskerLeftExpr (.of f) η₁ - let ⟨ηs₁, pf_ηs₁⟩ ← evalWhiskerRightExpr ηs h - let α' := .whiskerRight α h - let ⟨ηs₂, pf_ηs₂⟩ ← evalComp (.associatorInv (.of f) g' h) ηs₁ - let ⟨η₃, pf_η₃⟩ ← evalComp η₂ ηs₂ - let ⟨η₄, pf_η₄⟩ ← evalComp (.associator (.of f) g h) η₃ - let ⟨η₅, pf_η₅⟩ ← evalComp (.nil α') η₄ - return ⟨η₅, ← mkAppM ``evalWhiskerRight_cons_whisker - #[pf_η₁, pf_η₂, pf_ηs₁, pf_ηs₂, pf_η₃, pf_η₄, pf_η₅]⟩ - | η, .comp g h => do - let ⟨η₁, pf_η₁⟩ ← evalWhiskerRightExpr η g - let ⟨η₂, pf_η₂⟩ ← evalWhiskerRightExpr η₁ h - let f := η.src - let f' := η.tgt - let ⟨η₃, pf_η₃⟩ ← evalComp η₂ (.associator f' g h) - let ⟨η₄, pf_η₄⟩ ← evalComp (.associatorInv f g h) η₃ - return ⟨η₄, ← mkAppM ``evalWhiskerRight_comp #[pf_η₁, pf_η₂, pf_η₃, pf_η₄]⟩ - | η, .id => do - let f := η.src - let g := η.tgt - let ⟨η₁, pf_η₁⟩ ← evalComp η (.rightUnitorInv g) - let ⟨η₂, pf_η₂⟩ ← evalComp (.rightUnitor f) η₁ - return ⟨η₂, ← mkAppM ``evalWhiskerRight_id #[pf_η₁, pf_η₂]⟩ - -/-- Evaluate the expression of a 2-morphism into a normalized form. -/ -partial def eval (e : Expr) : MonoidalM Result := do - if let .some α ← structuralAtom? e then - return ⟨.nil <| .atom α, ← mkEqRefl (← α.e)⟩ - else - match (← whnfR e).getAppFnArgs with - | (``CategoryStruct.id, #[_, _, f]) => - return ⟨.nil (.id (← toMor₁ f)), ← mkEqRefl (← mkAppM ``CategoryStruct.id #[f])⟩ - | (``CategoryStruct.comp, #[_, _, _, _, _, η, θ]) => - let ⟨η_e, pf_η⟩ ← eval η - let ⟨θ_e, pf_θ⟩ ← eval θ - let ⟨ηθ, pf⟩ ← evalComp η_e θ_e - return ⟨ηθ, ← mkAppM ``eval_comp #[pf_η, pf_θ, pf]⟩ - | (``MonoidalCategoryStruct.whiskerLeft, #[_, _, _, f, _, _, η]) => - let ⟨η_e, pf_η⟩ ← eval η - let ⟨θ, pf_θ⟩ ← evalWhiskerLeftExpr (← toMor₁ f) η_e - return ⟨θ, ← mkAppM ``eval_whiskerLeft #[pf_η, pf_θ]⟩ - | (``MonoidalCategoryStruct.whiskerRight, #[_, _, _, _, _, η, h]) => - let ⟨η_e, pf_η⟩ ← eval η - let ⟨θ, pf_θ⟩ ← evalWhiskerRightExpr η_e (← toMor₁ h) - return ⟨θ, ← mkAppM ``eval_whiskerRight #[pf_η, pf_θ]⟩ - | (``monoidalComp, #[C, _, _, _, _, _, _, η, θ]) => - let ⟨η_e, pf_η⟩ ← eval η - let α₀ ← structuralOfMonoidalComp C e - let α := NormalExpr.nil α₀ - let ⟨θ_e, pf_θ⟩ ← eval θ - let ⟨αθ, pf_θα⟩ ← evalComp α θ_e - let ⟨ηαθ, pf_ηαθ⟩ ← evalComp η_e αθ - return ⟨ηαθ, ← mkAppM ``eval_monoidalComp #[pf_η, pf_θ, pf_θα, pf_ηαθ]⟩ - | _ => - return ⟨← NormalExpr.ofExpr e, ← mkAppM ``eval_of #[e]⟩ - -/-- Convert a `NormalExpr` expression into a list of `WhiskerLeftExpr` expressions. -/ -def NormalExpr.toList : NormalExpr → List WhiskerLeftExpr - | NormalExpr.nil _ => [] - | NormalExpr.cons _ η ηs => η :: NormalExpr.toList ηs - -end Mathlib.Tactic.Monoidal - -open Mathlib.Tactic.Monoidal - -/-- `normalize% η` is the normalization of the 2-morphism `η`. -1. The normalized 2-morphism is of the form `α₀ ≫ η₀ ≫ α₁ ≫ η₁ ≫ ... αₘ ≫ ηₘ ≫ αₘ₊₁` where - each `αᵢ` is a structural 2-morphism (consisting of associators and unitors), -2. each `ηᵢ` is a non-structural 2-morphism of the form `f₁ ◁ ... ◁ fₘ ◁ θ`, and -3. `θ` is of the form `ι ▷ g₁ ▷ ... ▷ gₗ` --/ -elab "normalize% " t:term:51 : term => do - let e ← Lean.Elab.Term.elabTerm t none - let some ctx ← mkContext? e - | throwError "{← ppExpr e} is not a morphism" - MonoidalM.run ctx do (← eval e).expr.e - -theorem mk_eq {α : Type _} (a b a' b' : α) (ha : a = a') (hb : b = b') (h : a' = b') : a = b := by - simp [h, ha, hb] - -open Lean Elab Meta Tactic in -/-- Transform an equality between 2-morphisms into the equality between their normalizations. -/ -def mkEq (e : Expr) : MetaM Expr := do - let some (_, e₁, e₂) := (← whnfR <| e).eq? - | throwError "monoidal_nf requires an equality goal" - let some ctx ← mkContext? e₁ - | throwError "the lhs and rhs must be morphisms" - MonoidalM.run ctx do - let ⟨e₁', p₁⟩ ← eval e₁ - let ⟨e₂', p₂⟩ ← eval e₂ - mkAppM ``mk_eq #[e₁, e₂, ← e₁'.e, ← e₂'.e, p₁, p₂] - -open Lean Elab Tactic in -/-- Normalize the both sides of an equality. -/ -elab "monoidal_nf" : tactic => withMainContext do - let t ← getMainTarget - let mvarIds ← (← getMainGoal).apply (← mkEq t) - replaceMainGoal mvarIds diff --git a/Mathlib/Tactic/CategoryTheory/Monoidal/Basic.lean b/Mathlib/Tactic/CategoryTheory/Monoidal/Basic.lean new file mode 100644 index 0000000000000..6158728b44231 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Monoidal/Basic.lean @@ -0,0 +1,55 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Basic +import Mathlib.Tactic.CategoryTheory.Monoidal.Normalize +import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence + +/-! +# `monoidal` tactic + +This file provides `monoidal` tactic, which solves equations in a monoidal category, where +the two sides only differ by replacing strings of monoidal structural morphisms (that is, +associators, unitors, and identities) with different strings of structural morphisms with the same +source and target. In other words, `monoidal` solves equalities where both sides have the same +string diagrams. + +The core function for the `monoidal` tactic is provided in +`Mathlib.Tactic.CategoryTheory.Coherence.Basic`. See this file for more details about the +implementation. + +-/ + +open Lean Meta Elab Tactic +open CategoryTheory Mathlib.Tactic.BicategoryLike + +namespace Mathlib.Tactic.Monoidal + +/-- Normalize the both sides of an equality. -/ +def monoidalNf (mvarId : MVarId) : MetaM (List MVarId) := do + BicategoryLike.normalForm Monoidal.Context `monoidal mvarId + +@[inherit_doc monoidalNf] +elab "monoidal_nf" : tactic => withMainContext do + replaceMainGoal (← monoidalNf (← getMainGoal)) + +/-- +Use the coherence theorem for monoidal categories to solve equations in a monoidal category, +where the two sides only differ by replacing strings of monoidal structural morphisms +(that is, associators, unitors, and identities) +with different strings of structural morphisms with the same source and target. + +That is, `monoidal` can handle goals of the form +`a ≫ f ≫ b ≫ g ≫ c = a' ≫ f ≫ b' ≫ g ≫ c'` +where `a = a'`, `b = b'`, and `c = c'` can be proved using `monoidal_coherence`. +-/ +def monoidal (mvarId : MVarId) : MetaM (List MVarId) := + BicategoryLike.main Monoidal.Context `monoidal mvarId + +@[inherit_doc monoidal] +elab "monoidal" : tactic => withMainContext do + replaceMainGoal <| ← monoidal <| ← getMainGoal + +end Mathlib.Tactic.Monoidal diff --git a/Mathlib/Tactic/CategoryTheory/Monoidal/Datatypes.lean b/Mathlib/Tactic/CategoryTheory/Monoidal/Datatypes.lean new file mode 100644 index 0000000000000..43c3ef94fc6cc --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Monoidal/Datatypes.lean @@ -0,0 +1,505 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Datatypes +import Mathlib.Tactic.CategoryTheory.MonoidalComp + +/-! +# Expressions for monoidal categories + +This file converts lean expressions representing morphisms in monoidal categories into `Mor₂Iso` +or `Mor` terms. The converted expressions are used in the coherence tactics and the string diagram +widgets. + +-/ + +open Lean Meta Elab Qq +open CategoryTheory Mathlib.Tactic.BicategoryLike MonoidalCategory + +namespace Mathlib.Tactic.Monoidal + +/-- The domain of a morphism. -/ +def srcExpr (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Quiver.Hom, #[_, _, f, _]) => return f + | _ => throwError m!"{η} is not a morphism" + +/-- The codomain of a morphism. -/ +def tgtExpr (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Quiver.Hom, #[_, _, _, g]) => return g + | _ => throwError m!"{η} is not a morphism" + +/-- The domain of an isomorphism. -/ +def srcExprOfIso (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Iso, #[_, _, f, _]) => return f + | _ => throwError m!"{η} is not a morphism" + +/-- The codomain of an isomorphism. -/ +def tgtExprOfIso (η : Expr) : MetaM Expr := do + match (← whnfR (← inferType η)).getAppFnArgs with + | (``Iso, #[_, _, _, g]) => return g + | _ => throwError m!"{η} is not a morphism" + +initialize registerTraceClass `monoidal + +/-- The context for evaluating expressions. -/ +structure Context where + /-- The level for morphisms. -/ + level₂ : Level + /-- The level for objects. -/ + level₁ : Level + /-- The expression for the underlying category. -/ + C : Q(Type level₁) + /-- The category instance. -/ + instCat : Q(Category.{level₂, level₁} $C) + /-- The monoidal category instance. -/ + instMonoidal? : Option Q(MonoidalCategory.{level₂, level₁} $C) + +/-- Populate a `context` object for evaluating `e`. -/ +def mkContext? (e : Expr) : MetaM (Option Context) := do + let e ← instantiateMVars e + let type ← instantiateMVars <| ← inferType e + match (← whnfR type).getAppFnArgs with + | (``Quiver.Hom, #[_, _, f, _]) => + let C ← instantiateMVars <| ← inferType f + let .succ level₁ ← getLevel C | return none + let .succ level₂ ← getLevel type | return none + let .some instCat ← synthInstance? + (mkAppN (.const ``Category [level₂, level₁]) #[C]) | return none + let instMonoidal? ← synthInstance? + (mkAppN (.const ``MonoidalCategory [level₂, level₁]) #[C, instCat]) + return some ⟨level₂, level₁, C, instCat, instMonoidal?⟩ + | _ => return none + +instance : BicategoryLike.Context Monoidal.Context where + mkContext? := Monoidal.mkContext? + +/-- The monad for the normalization of 2-morphisms. -/ +abbrev MonoidalM := CoherenceM Context + +/-- Throw an error if the monoidal category instance is not found. -/ +def synthMonoidalError {α : Type} : MetaM α := do + throwError "failed to find monoidal category instance" + +instance : MonadMor₁ MonoidalM where + id₁M a := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + return .id (q(MonoidalCategory.tensorUnit) : Q($ctx.C)) a + comp₁M f g := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f_e : Q($ctx.C) := f.e + let g_e : Q($ctx.C) := g.e + return .comp (q($f_e ⊗ $g_e)) f g + +section + +universe v u +variable {C : Type u} [Category.{v} C] + +theorem structuralIsoOfExpr_comp {f g h : C} + (η : f ⟶ g) (η' : f ≅ g) (ih_η : η'.hom = η) + (θ : g ⟶ h) (θ' : g ≅ h) (ih_θ : θ'.hom = θ) : + (η' ≪≫ θ').hom = η ≫ θ := by + simp [ih_η, ih_θ] + +theorem StructuralOfExpr_monoidalComp {f g h i : C} [MonoidalCoherence g h] + (η : f ⟶ g) (η' : f ≅ g) (ih_η : η'.hom = η) (θ : h ⟶ i) (θ' : h ≅ i) (ih_θ : θ'.hom = θ) : + (η' ≪⊗≫ θ').hom = η ⊗≫ θ := by + simp [ih_η, ih_θ, monoidalIsoComp, monoidalComp, MonoidalCoherence.iso] + +variable [MonoidalCategory C] + +theorem structuralIsoOfExpr_whiskerLeft (f : C) {g h : C} + (η : g ⟶ h) (η' : g ≅ h) (ih_η : η'.hom = η) : + (whiskerLeftIso f η').hom = f ◁ η := by + simp [ih_η] + +theorem structuralIsoOfExpr_whiskerRight {f g : C} (h : C) + (η : f ⟶ g) (η' : f ≅ g) (ih_η : η'.hom = η) : + (whiskerRightIso η' h).hom = η ▷ h := by + simp [ih_η] + +theorem structuralIsoOfExpr_horizontalComp {f₁ g₁ f₂ g₂ : C} + (η : f₁ ⟶ g₁) (η' : f₁ ≅ g₁) (ih_η : η'.hom = η) + (θ : f₂ ⟶ g₂) (θ' : f₂ ≅ g₂) (ih_θ : θ'.hom = θ) : + (η' ⊗ θ').hom = η ⊗ θ := by + simp [ih_η, ih_θ] + +end + +open MonadMor₁ + +instance : MonadMor₂Iso MonoidalM where + associatorM f g h := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f_e : Q($ctx.C) := f.e + let g_e : Q($ctx.C) := g.e + let h_e : Q($ctx.C) := h.e + return .associator q(α_ $f_e $g_e $h_e) f g h + leftUnitorM f := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f_e : Q($ctx.C) := f.e + return .leftUnitor q(λ_ $f_e) f + rightUnitorM f := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f_e : Q($ctx.C) := f.e + return .rightUnitor q(ρ_ $f_e) f + id₂M f := do + let ctx ← read + let _cat := ctx.instCat + have f_e : Q($ctx.C) := f.e + return .id q(Iso.refl $f_e) f + coherenceHomM f g inst := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have inst : Q(MonoidalCoherence $f_e $g_e) := inst + match (← whnfI inst).getAppFnArgs with + | (``MonoidalCoherence.mk, #[_, _, _, _, α]) => + let e : Q($f_e ≅ $g_e) := q(MonoidalCoherence.iso) + return ⟨e, f, g, inst, α⟩ + | _ => throwError m!"failed to unfold {inst}" + comp₂M η θ := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + let h ← θ.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have η_e : Q($f_e ≅ $g_e) := η.e + have θ_e : Q($g_e ≅ $h_e) := θ.e + return .comp q($η_e ≪≫ $θ_e) f g h η θ + whiskerLeftM f η := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← η.srcM + let h ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have η_e : Q($g_e ≅ $h_e) := η.e + return .whiskerLeft q(whiskerLeftIso $f_e $η_e) f g h η + whiskerRightM η h := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .whiskerRight q(whiskerRightIso $η_e $h_e) f g η h + horizontalCompM η θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f₁ ← η.srcM + let g₁ ← η.tgtM + let f₂ ← θ.srcM + let g₂ ← θ.tgtM + have f₁_e : Q($ctx.C) := f₁.e + have g₁_e : Q($ctx.C) := g₁.e + have f₂_e : Q($ctx.C) := f₂.e + have g₂_e : Q($ctx.C) := g₂.e + have η_e : Q($f₁_e ≅ $g₁_e) := η.e + have θ_e : Q($f₂_e ≅ $g₂_e) := θ.e + return .horizontalComp q(tensorIso $η_e $θ_e) f₁ g₁ f₂ g₂ η θ + symmM η := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .inv q(Iso.symm $η_e) f g η + coherenceCompM α η θ := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + let h ← θ.srcM + let i ← θ.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have i_e : Q($ctx.C) := i.e + have _inst : Q(MonoidalCoherence $g_e $h_e) := α.inst + have η_e : Q($f_e ≅ $g_e) := η.e + have θ_e : Q($h_e ≅ $i_e) := θ.e + return .coherenceComp q($η_e ≪⊗≫ $θ_e) f g h i α η θ + +open MonadMor₂Iso + +instance : MonadMor₂ MonoidalM where + homM η := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + let e : Q($f_e ⟶ $g_e) := q(Iso.hom $η_e) + have eq : Q(Iso.hom $η_e = $e) := q(rfl) + return .isoHom e ⟨η, eq⟩ η + atomHomM η := do + let ctx ← read + let _cat := ctx.instCat + let f := η.src + let g := η.tgt + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .mk q(Iso.hom $η_e) f g + invM η := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + let e : Q($g_e ⟶ $f_e) := q(Iso.inv $η_e) + let η_inv ← symmM η + let eq : Q(Iso.inv $η_e = $e) := q(Iso.symm_hom $η_e) + return .isoInv e ⟨η_inv, eq⟩ η + atomInvM η := do + let ctx ← read + let _cat := ctx.instCat + let f := η.src + let g := η.tgt + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have η_e : Q($f_e ≅ $g_e) := η.e + return .mk q(Iso.inv $η_e) g f + id₂M f := do + let ctx ← read + let _cat := ctx.instCat + have f_e : Q($ctx.C) := f.e + let e : Q($f_e ⟶ $f_e) := q(𝟙 $f_e) + let eq : Q(𝟙 $f_e = $e) := q(Iso.refl_hom $f_e) + return .id e ⟨.structuralAtom <| ← id₂M f, eq⟩ f + comp₂M η θ := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + let h ← θ.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have η_e : Q($f_e ⟶ $g_e) := η.e + have θ_e : Q($g_e ⟶ $h_e) := θ.e + let iso_lift? ← (match (η.isoLift?, θ.isoLift?) with + | (some η_iso, some θ_iso) => + have η_iso_e : Q($f_e ≅ $g_e) := η_iso.e.e + have θ_iso_e : Q($g_e ≅ $h_e) := θ_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + have θ_iso_eq : Q(Iso.hom $θ_iso_e = $θ_e) := θ_iso.eq + let eq := q(structuralIsoOfExpr_comp _ _ $η_iso_eq _ _ $θ_iso_eq) + return .some ⟨← comp₂M η_iso.e θ_iso.e, eq⟩ + | _ => return none) + let e : Q($f_e ⟶ $h_e) := q($η_e ≫ $θ_e) + return .comp e iso_lift? f g h η θ + whiskerLeftM f η := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← η.srcM + let h ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have η_e : Q($g_e ⟶ $h_e) := η.e + let iso_lift? ← (match η.isoLift? with + | some η_iso => do + have η_iso_e : Q($g_e ≅ $h_e) := η_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + let eq := q(structuralIsoOfExpr_whiskerLeft $f_e _ _ $η_iso_eq) + return .some ⟨← whiskerLeftM f η_iso.e, eq⟩ + | _ => return none) + let e : Q($f_e ⊗ $g_e ⟶ $f_e ⊗ $h_e) := q($f_e ◁ $η_e) + return .whiskerLeft e iso_lift? f g h η + whiskerRightM η h := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have η_e : Q($f_e ⟶ $g_e) := η.e + let iso_lift? ← (match η.isoLift? with + | some η_iso => do + have η_iso_e : Q($f_e ≅ $g_e) := η_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + let eq := q(structuralIsoOfExpr_whiskerRight $h_e _ _ $η_iso_eq) + return .some ⟨← whiskerRightM η_iso.e h, eq⟩ + | _ => return none) + let e : Q($f_e ⊗ $h_e ⟶ $g_e ⊗ $h_e) := q($η_e ▷ $h_e) + return .whiskerRight e iso_lift? f g η h + horizontalCompM η θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f₁ ← η.srcM + let g₁ ← η.tgtM + let f₂ ← θ.srcM + let g₂ ← θ.tgtM + have f₁_e : Q($ctx.C) := f₁.e + have g₁_e : Q($ctx.C) := g₁.e + have f₂_e : Q($ctx.C) := f₂.e + have g₂_e : Q($ctx.C) := g₂.e + have η_e : Q($f₁_e ⟶ $g₁_e) := η.e + have θ_e : Q($f₂_e ⟶ $g₂_e) := θ.e + let iso_lift? ← (match (η.isoLift?, θ.isoLift?) with + | (some η_iso, some θ_iso) => do + have η_iso_e : Q($f₁_e ≅ $g₁_e) := η_iso.e.e + have θ_iso_e : Q($f₂_e ≅ $g₂_e) := θ_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + have θ_iso_eq : Q(Iso.hom $θ_iso_e = $θ_e) := θ_iso.eq + let eq := q(structuralIsoOfExpr_horizontalComp _ _ $η_iso_eq _ _ $θ_iso_eq) + return .some ⟨← horizontalCompM η_iso.e θ_iso.e, eq⟩ + | _ => return none) + let e : Q($f₁_e ⊗ $f₂_e ⟶ $g₁_e ⊗ $g₂_e) := q($η_e ⊗ $θ_e) + return .horizontalComp e iso_lift? f₁ g₁ f₂ g₂ η θ + coherenceCompM α η θ := do + let ctx ← read + let _cat := ctx.instCat + let f ← η.srcM + let g ← η.tgtM + let h ← θ.srcM + let i ← θ.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have i_e : Q($ctx.C) := i.e + have _inst : Q(MonoidalCoherence $g_e $h_e) := α.inst + have η_e : Q($f_e ⟶ $g_e) := η.e + have θ_e : Q($h_e ⟶ $i_e) := θ.e + let iso_lift? ← (match (η.isoLift?, θ.isoLift?) with + | (some η_iso, some θ_iso) => do + have η_iso_e : Q($f_e ≅ $g_e) := η_iso.e.e + have θ_iso_e : Q($h_e ≅ $i_e) := θ_iso.e.e + have η_iso_eq : Q(Iso.hom $η_iso_e = $η_e) := η_iso.eq + have θ_iso_eq : Q(Iso.hom $θ_iso_e = $θ_e) := θ_iso.eq + let eq := q(StructuralOfExpr_monoidalComp _ _ $η_iso_eq _ _ $θ_iso_eq) + return .some ⟨← coherenceCompM α η_iso.e θ_iso.e, eq⟩ + | _ => return none) + let e : Q($f_e ⟶ $i_e) := q($η_e ⊗≫ $θ_e) + return .coherenceComp e iso_lift? f g h i α η θ + +/-- Check that `e` is definitionally equal to `𝟙_ C`. -/ +def id₁? (e : Expr) : MonoidalM (Option Obj) := do + let ctx ← read + match ctx.instMonoidal? with + | .some _monoidal => do + if ← withDefault <| isDefEq e (q(MonoidalCategory.tensorUnit) : Q($ctx.C)) then + return some ⟨none⟩ + else + return none + | _ => return none + +/-- Return `(f, g)` if `e` is definitionally equal to `f ⊗ g`. -/ +def comp? (e : Expr) : MonoidalM (Option (Mor₁ × Mor₁)) := do + let ctx ← read + let f ← mkFreshExprMVarQ ctx.C + let g ← mkFreshExprMVarQ ctx.C + match ctx.instMonoidal? with + | .some _monoidal => do + if ← withDefault <| isDefEq e q($f ⊗ $g) then + let f ← instantiateMVars f + let g ← instantiateMVars g + return some ((.of ⟨f, ⟨none⟩, ⟨none⟩⟩ : Mor₁), (.of ⟨g, ⟨none⟩, ⟨none⟩⟩ : Mor₁)) + else + return none + | _ => return none + +/-- Construct a `Mor₁` expression from a Lean expression. -/ +partial def mor₁OfExpr (e : Expr) : MonoidalM Mor₁ := do + if let some f := (← get).cache.find? e then + return f + let f ← + if let some a ← id₁? e then + MonadMor₁.id₁M a + else if let some (f, g) ← comp? e then + MonadMor₁.comp₁M (← mor₁OfExpr f.e) (← mor₁OfExpr g.e) + else + return Mor₁.of ⟨e, ⟨none⟩, ⟨none⟩⟩ + modify fun s => { s with cache := s.cache.insert e f } + return f + +instance : MkMor₁ MonoidalM where + ofExpr := mor₁OfExpr + +/-- Construct a `Mor₂Iso` term from a Lean expression. -/ +partial def Mor₂IsoOfExpr (e : Expr) : MonoidalM Mor₂Iso := do + match (← whnfR e).getAppFnArgs with + | (``MonoidalCategoryStruct.associator, #[_, _, _, f, g, h]) => + associatorM' (← MkMor₁.ofExpr f) (← MkMor₁.ofExpr g) (← MkMor₁.ofExpr h) + | (``MonoidalCategoryStruct.leftUnitor, #[_, _, _, f]) => + leftUnitorM' (← MkMor₁.ofExpr f) + | (``MonoidalCategoryStruct.rightUnitor, #[_, _, _, f]) => + rightUnitorM' (← MkMor₁.ofExpr f) + | (``Iso.refl, #[_, _, f]) => + id₂M' (← MkMor₁.ofExpr f) + | (``Iso.symm, #[_, _, _, _, η]) => + symmM (← Mor₂IsoOfExpr η) + | (``Iso.trans, #[_, _, _, _, _, η, θ]) => + comp₂M (← Mor₂IsoOfExpr η) (← Mor₂IsoOfExpr θ) + | (``MonoidalCategory.whiskerLeftIso, #[_, _, _, f, _, _, η]) => + whiskerLeftM (← MkMor₁.ofExpr f) (← Mor₂IsoOfExpr η) + | (``MonoidalCategory.whiskerRightIso, #[_, _, _, _, _, η, h]) => + whiskerRightM (← Mor₂IsoOfExpr η) (← MkMor₁.ofExpr h) + | (``tensorIso, #[_, _, _, _, _, _, _, η, θ]) => + horizontalCompM (← Mor₂IsoOfExpr η) (← Mor₂IsoOfExpr θ) + | (``monoidalIsoComp, #[_, _, _, g, h, _, inst, η, θ]) => + let α ← coherenceHomM (← MkMor₁.ofExpr g) (← MkMor₁.ofExpr h) inst + coherenceCompM α (← Mor₂IsoOfExpr η) (← Mor₂IsoOfExpr θ) + | (``MonoidalCoherence.iso, #[_, _, f, g, inst]) => + coherenceHomM' (← MkMor₁.ofExpr f) (← MkMor₁.ofExpr g) inst + | _ => + return .of ⟨e, ← MkMor₁.ofExpr (← srcExprOfIso e), ← MkMor₁.ofExpr (← tgtExprOfIso e)⟩ + +open MonadMor₂ in +/-- Construct a `Mor₂` term from a Lean expression. -/ +partial def Mor₂OfExpr (e : Expr) : MonoidalM Mor₂ := do + match ← whnfR e with + -- whnfR version of `Iso.hom η` + | .proj ``Iso 0 η => homM (← Mor₂IsoOfExpr η) + -- whnfR version of `Iso.inv η` + | .proj ``Iso 1 η => invM (← Mor₂IsoOfExpr η) + | .app .. => match (← whnfR e).getAppFnArgs with + | (``CategoryStruct.id, #[_, _, f]) => id₂M (← MkMor₁.ofExpr f) + | (``CategoryStruct.comp, #[_, _, _, _, _, η, θ]) => + comp₂M (← Mor₂OfExpr η) (← Mor₂OfExpr θ) + | (``MonoidalCategoryStruct.whiskerLeft, #[_, _, _, f, _, _, η]) => + whiskerLeftM (← MkMor₁.ofExpr f) (← Mor₂OfExpr η) + | (``MonoidalCategoryStruct.whiskerRight, #[_, _, _, _, _, η, h]) => + whiskerRightM (← Mor₂OfExpr η) (← MkMor₁.ofExpr h) + | (``MonoidalCategoryStruct.tensorHom, #[_, _, _, _, _, _, _, η, θ]) => + horizontalCompM (← Mor₂OfExpr η) (← Mor₂OfExpr θ) + | (``monoidalComp, #[_, _, _, g, h, _, inst, η, θ]) => + let α ← coherenceHomM (← MkMor₁.ofExpr g) (← MkMor₁.ofExpr h) inst + coherenceCompM α (← Mor₂OfExpr η) (← Mor₂OfExpr θ) + | _ => return .of ⟨e, ← MkMor₁.ofExpr (← srcExpr e), ← MkMor₁.ofExpr (← tgtExpr e)⟩ + | _ => + return .of ⟨e, ← MkMor₁.ofExpr (← srcExpr e), ← MkMor₁.ofExpr (← tgtExpr e)⟩ + +instance : BicategoryLike.MkMor₂ MonoidalM where + ofExpr := Mor₂OfExpr + +instance : MonadCoherehnceHom MonoidalM where + unfoldM α := Mor₂IsoOfExpr α.unfold + +end Mathlib.Tactic.Monoidal diff --git a/Mathlib/Tactic/CategoryTheory/Monoidal/Normalize.lean b/Mathlib/Tactic/CategoryTheory/Monoidal/Normalize.lean new file mode 100644 index 0000000000000..f55e98f5088b0 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Monoidal/Normalize.lean @@ -0,0 +1,787 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.Normalize +import Mathlib.Tactic.CategoryTheory.Monoidal.Datatypes + +/-! +# Normalization of morphisms in monoidal categories + +This file provides the implementation of the normalization given in +`Mathlib.Tactic.CategoryTheory.Coherence.Normalize`. See this file for more details. + +-/ + +open Lean Meta Elab Qq +open CategoryTheory Mathlib.Tactic.BicategoryLike MonoidalCategory + +namespace Mathlib.Tactic.Monoidal + +section + +universe v u + +variable {C : Type u} [Category.{v} C] + +variable {f f' g g' h h' i i' j : C} + +@[nolint synTaut] +theorem evalComp_nil_nil {f g h : C} (α : f ≅ g) (β : g ≅ h) : + (α ≪≫ β).hom = (α ≪≫ β).hom := by + simp + +theorem evalComp_nil_cons {f g h i j : C} (α : f ≅ g) (β : g ≅ h) (η : h ⟶ i) (ηs : i ⟶ j) : + α.hom ≫ (β.hom ≫ η ≫ ηs) = (α ≪≫ β).hom ≫ η ≫ ηs := by + simp + +theorem evalComp_cons {f g h i j : C} (α : f ≅ g) (η : g ⟶ h) {ηs : h ⟶ i} {θ : i ⟶ j} {ι : h ⟶ j} + (e_ι : ηs ≫ θ = ι) : + (α.hom ≫ η ≫ ηs) ≫ θ = α.hom ≫ η ≫ ι := by + simp [e_ι] + +theorem eval_comp + {η η' : f ⟶ g} {θ θ' : g ⟶ h} {ι : f ⟶ h} + (e_η : η = η') (e_θ : θ = θ') (e_ηθ : η' ≫ θ' = ι) : + η ≫ θ = ι := by + simp [e_η, e_θ, e_ηθ] + +theorem eval_of (η : f ⟶ g) : + η = (Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom := by + simp + +theorem eval_monoidalComp + {η η' : f ⟶ g} {α : g ≅ h} {θ θ' : h ⟶ i} {αθ : g ⟶ i} {ηαθ : f ⟶ i} + (e_η : η = η') (e_θ : θ = θ') (e_αθ : α.hom ≫ θ' = αθ) (e_ηαθ : η' ≫ αθ = ηαθ) : + η ≫ α.hom ≫ θ = ηαθ := by + simp [e_η, e_θ, e_αθ, e_ηαθ] + +variable [MonoidalCategory C] + +@[nolint synTaut] +theorem evalWhiskerLeft_nil (f : C) {g h : C} (α : g ≅ h) : + (whiskerLeftIso f α).hom = (whiskerLeftIso f α).hom := by + simp + +theorem evalWhiskerLeft_of_cons {f g h i j : C} + (α : g ≅ h) (η : h ⟶ i) {ηs : i ⟶ j} {θ : f ⊗ i ⟶ f ⊗ j} (e_θ : f ◁ ηs = θ) : + f ◁ (α.hom ≫ η ≫ ηs) = (whiskerLeftIso f α).hom ≫ f ◁ η ≫ θ := by + simp [e_θ] + +theorem evalWhiskerLeft_comp {f g h i : C} + {η : h ⟶ i} {η₁ : g ⊗ h ⟶ g ⊗ i} {η₂ : f ⊗ g ⊗ h ⟶ f ⊗ g ⊗ i} + {η₃ : f ⊗ g ⊗ h ⟶ (f ⊗ g) ⊗ i} {η₄ : (f ⊗ g) ⊗ h ⟶ (f ⊗ g) ⊗ i} + (e_η₁ : g ◁ η = η₁) (e_η₂ : f ◁ η₁ = η₂) + (e_η₃ : η₂ ≫ (α_ _ _ _).inv = η₃) (e_η₄ : (α_ _ _ _).hom ≫ η₃ = η₄) : + (f ⊗ g) ◁ η = η₄ := by + simp [e_η₁, e_η₂, e_η₃, e_η₄] + +theorem evalWhiskerLeft_id {f g : C} {η : f ⟶ g} + {η₁ : f ⟶ 𝟙_ C ⊗ g} {η₂ : 𝟙_ C ⊗ f ⟶ 𝟙_ C ⊗ g} + (e_η₁ : η ≫ (λ_ _).inv = η₁) (e_η₂ : (λ_ _).hom ≫ η₁ = η₂) : + 𝟙_ C ◁ η = η₂ := by + simp [e_η₁, e_η₂] + +theorem eval_whiskerLeft {f g h : C} + {η η' : g ⟶ h} {θ : f ⊗ g ⟶ f ⊗ h} + (e_η : η = η') (e_θ : f ◁ η' = θ) : + f ◁ η = θ := by + simp [e_η, e_θ] + +theorem eval_whiskerRight {f g h : C} + {η η' : f ⟶ g} {θ : f ⊗ h ⟶ g ⊗ h} + (e_η : η = η') (e_θ : η' ▷ h = θ) : + η ▷ h = θ := by + simp [e_η, e_θ] + +theorem eval_tensorHom {f g h i : C} + {η η' : f ⟶ g} {θ θ' : h ⟶ i} {ι : f ⊗ h ⟶ g ⊗ i} + (e_η : η = η') (e_θ : θ = θ') (e_ι : η' ⊗ θ' = ι) : + η ⊗ θ = ι := by + simp [e_η, e_θ, e_ι] + +@[nolint synTaut] +theorem evalWhiskerRight_nil {f g : C} (α : f ≅ g) (h : C) : + (whiskerRightIso α h).hom = (whiskerRightIso α h).hom := by + simp + +theorem evalWhiskerRight_cons_of_of {f g h i j : C} + {α : f ≅ g} {η : g ⟶ h} {ηs : h ⟶ i} {ηs₁ : h ⊗ j ⟶ i ⊗ j} + {η₁ : g ⊗ j ⟶ h ⊗ j} {η₂ : g ⊗ j ⟶ i ⊗ j} {η₃ : f ⊗ j ⟶ i ⊗ j} + (e_ηs₁ : ηs ▷ j = ηs₁) (e_η₁ : η ▷ j = η₁) + (e_η₂ : η₁ ≫ ηs₁ = η₂) (e_η₃ : (whiskerRightIso α j).hom ≫ η₂ = η₃) : + (α.hom ≫ η ≫ ηs) ▷ j = η₃ := by + simp_all + +theorem evalWhiskerRight_cons_whisker {f g h i j k : C} + {α : g ≅ f ⊗ h} {η : h ⟶ i} {ηs : f ⊗ i ⟶ j} + {η₁ : h ⊗ k ⟶ i ⊗ k} {η₂ : f ⊗ (h ⊗ k) ⟶ f ⊗ (i ⊗ k)} {ηs₁ : (f ⊗ i) ⊗ k ⟶ j ⊗ k} + {ηs₂ : f ⊗ (i ⊗ k) ⟶ j ⊗ k} {η₃ : f ⊗ (h ⊗ k) ⟶ j ⊗ k} {η₄ : (f ⊗ h) ⊗ k ⟶ j ⊗ k} + {η₅ : g ⊗ k ⟶ j ⊗ k} + (e_η₁ : ((Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom) ▷ k = η₁) (e_η₂ : f ◁ η₁ = η₂) + (e_ηs₁ : ηs ▷ k = ηs₁) (e_ηs₂ : (α_ _ _ _).inv ≫ ηs₁ = ηs₂) + (e_η₃ : η₂ ≫ ηs₂ = η₃) (e_η₄ : (α_ _ _ _).hom ≫ η₃ = η₄) + (e_η₅ : (whiskerRightIso α k).hom ≫ η₄ = η₅) : + (α.hom ≫ (f ◁ η) ≫ ηs) ▷ k = η₅ := by + simp at e_η₁ e_η₅ + simp [e_η₁, e_η₂, e_ηs₁, e_ηs₂, e_η₃, e_η₄, e_η₅] + +theorem evalWhiskerRight_comp {f f' g h : C} + {η : f ⟶ f'} {η₁ : f ⊗ g ⟶ f' ⊗ g} {η₂ : (f ⊗ g) ⊗ h ⟶ (f' ⊗ g) ⊗ h} + {η₃ : (f ⊗ g) ⊗ h ⟶ f' ⊗ (g ⊗ h)} {η₄ : f ⊗ (g ⊗ h) ⟶ f' ⊗ (g ⊗ h)} + (e_η₁ : η ▷ g = η₁) (e_η₂ : η₁ ▷ h = η₂) + (e_η₃ : η₂ ≫ (α_ _ _ _).hom = η₃) (e_η₄ : (α_ _ _ _).inv ≫ η₃ = η₄) : + η ▷ (g ⊗ h) = η₄ := by + simp [e_η₁, e_η₂, e_η₃, e_η₄] + +theorem evalWhiskerRight_id {f g : C} + {η : f ⟶ g} {η₁ : f ⟶ g ⊗ 𝟙_ C} {η₂ : f ⊗ 𝟙_ C ⟶ g ⊗ 𝟙_ C} + (e_η₁ : η ≫ (ρ_ _).inv = η₁) (e_η₂ : (ρ_ _).hom ≫ η₁ = η₂) : + η ▷ 𝟙_ C = η₂ := by + simp [e_η₁, e_η₂] + +theorem evalWhiskerRightAux_of {f g : C} (η : f ⟶ g) (h : C) : + η ▷ h = (Iso.refl _).hom ≫ η ▷ h ≫ (Iso.refl _).hom := by + simp + +theorem evalWhiskerRightAux_cons {f g h i j : C} {η : g ⟶ h} {ηs : i ⟶ j} + {ηs' : i ⊗ f ⟶ j ⊗ f} {η₁ : g ⊗ (i ⊗ f) ⟶ h ⊗ (j ⊗ f)} + {η₂ : g ⊗ (i ⊗ f) ⟶ (h ⊗ j) ⊗ f} {η₃ : (g ⊗ i) ⊗ f ⟶ (h ⊗ j) ⊗ f} + (e_ηs' : ηs ▷ f = ηs') (e_η₁ : ((Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom) ⊗ ηs' = η₁) + (e_η₂ : η₁ ≫ (α_ _ _ _).inv = η₂) (e_η₃ : (α_ _ _ _).hom ≫ η₂ = η₃) : + (η ⊗ ηs) ▷ f = η₃ := by + simp [← e_ηs', ← e_η₁, ← e_η₂, ← e_η₃, MonoidalCategory.tensorHom_def] + +theorem evalWhiskerRight_cons_of {f f' g h i : C} {α : f' ≅ g} {η : g ⟶ h} {ηs : h ⟶ i} + {ηs₁ : h ⊗ f ⟶ i ⊗ f} {η₁ : g ⊗ f ⟶ h ⊗ f} {η₂ : g ⊗ f ⟶ i ⊗ f} + {η₃ : f' ⊗ f ⟶ i ⊗ f} + (e_ηs₁ : ηs ▷ f = ηs₁) (e_η₁ : η ▷ f = η₁) + (e_η₂ : η₁ ≫ ηs₁ = η₂) (e_η₃ : (whiskerRightIso α f).hom ≫ η₂ = η₃) : + (α.hom ≫ η ≫ ηs) ▷ f = η₃ := by + simp_all + +theorem evalHorizontalCompAux_of {f g h i : C} (η : f ⟶ g) (θ : h ⟶ i) : + η ⊗ θ = (Iso.refl _).hom ≫ (η ⊗ θ) ≫ (Iso.refl _).hom := by + simp + +theorem evalHorizontalCompAux_cons {f f' g g' h i : C} {η : f ⟶ g} {ηs : f' ⟶ g'} {θ : h ⟶ i} + {ηθ : f' ⊗ h ⟶ g' ⊗ i} {η₁ : f ⊗ (f' ⊗ h) ⟶ g ⊗ (g' ⊗ i)} + {ηθ₁ : f ⊗ (f' ⊗ h) ⟶ (g ⊗ g') ⊗ i} {ηθ₂ : (f ⊗ f') ⊗ h ⟶ (g ⊗ g') ⊗ i} + (e_ηθ : ηs ⊗ θ = ηθ) (e_η₁ : ((Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom) ⊗ ηθ = η₁) + (e_ηθ₁ : η₁ ≫ (α_ _ _ _).inv = ηθ₁) (e_ηθ₂ : (α_ _ _ _).hom ≫ ηθ₁ = ηθ₂) : + (η ⊗ ηs) ⊗ θ = ηθ₂ := by + simp_all + +theorem evalHorizontalCompAux'_whisker {f f' g g' h : C} {η : g ⟶ h} {θ : f' ⟶ g'} + {ηθ : g ⊗ f' ⟶ h ⊗ g'} {η₁ : f ⊗ (g ⊗ f') ⟶ f ⊗ (h ⊗ g')} + {η₂ : f ⊗ (g ⊗ f') ⟶ (f ⊗ h) ⊗ g'} {η₃ : (f ⊗ g) ⊗ f' ⟶ (f ⊗ h) ⊗ g'} + (e_ηθ : η ⊗ θ = ηθ) (e_η₁ : f ◁ ηθ = η₁) + (e_η₂ : η₁ ≫ (α_ _ _ _).inv = η₂) (e_η₃ : (α_ _ _ _).hom ≫ η₂ = η₃) : + (f ◁ η) ⊗ θ = η₃ := by + simp only [← e_ηθ, ← e_η₁, ← e_η₂, ← e_η₃] + simp [MonoidalCategory.tensorHom_def] + +theorem evalHorizontalCompAux'_of_whisker {f f' g g' h : C} {η : g ⟶ h} {θ : f' ⟶ g'} + {η₁ : g ⊗ f ⟶ h ⊗ f} {ηθ : (g ⊗ f) ⊗ f' ⟶ (h ⊗ f) ⊗ g'} + {ηθ₁ : (g ⊗ f) ⊗ f' ⟶ h ⊗ (f ⊗ g')} + {ηθ₂ : g ⊗ (f ⊗ f') ⟶ h ⊗ (f ⊗ g')} + (e_η₁ : η ▷ f = η₁) (e_ηθ : η₁ ⊗ ((Iso.refl _).hom ≫ θ ≫ (Iso.refl _).hom) = ηθ) + (e_ηθ₁ : ηθ ≫ (α_ _ _ _).hom = ηθ₁) (e_ηθ₂ : (α_ _ _ _).inv ≫ ηθ₁ = ηθ₂) : + η ⊗ (f ◁ θ) = ηθ₂ := by + simp only [← e_η₁, ← e_ηθ, ← e_ηθ₁, ← e_ηθ₂] + simp [MonoidalCategory.tensorHom_def] + +@[nolint synTaut] +theorem evalHorizontalComp_nil_nil {f g h i : C} (α : f ≅ g) (β : h ≅ i) : + (α ⊗ β).hom = (α ⊗ β).hom := by + simp + +theorem evalHorizontalComp_nil_cons {f f' g g' h i : C} + {α : f ≅ g} {β : f' ≅ g'} {η : g' ⟶ h} {ηs : h ⟶ i} + {η₁ : g ⊗ g' ⟶ g ⊗ h} {ηs₁ : g ⊗ h ⟶ g ⊗ i} + {η₂ : g ⊗ g' ⟶ g ⊗ i} {η₃ : f ⊗ f' ⟶ g ⊗ i} + (e_η₁ : g ◁ ((Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom) = η₁) + (e_ηs₁ : g ◁ ηs = ηs₁) (e_η₂ : η₁ ≫ ηs₁ = η₂) + (e_η₃ : (α ⊗ β).hom ≫ η₂ = η₃) : + α.hom ⊗ (β.hom ≫ η ≫ ηs) = η₃ := by + simp_all [MonoidalCategory.tensorHom_def] + +theorem evalHorizontalComp_cons_nil {f f' g g' h i : C} + {α : f ≅ g} {η : g ⟶ h} {ηs : h ⟶ i} {β : f' ≅ g'} + {η₁ : g ⊗ g' ⟶ h ⊗ g'} {ηs₁ : h ⊗ g' ⟶ i ⊗ g'} {η₂ : g ⊗ g' ⟶ i ⊗ g'} {η₃ : f ⊗ f' ⟶ i ⊗ g'} + (e_η₁ : ((Iso.refl _).hom ≫ η ≫ (Iso.refl _).hom) ▷ g' = η₁) (e_ηs₁ : ηs ▷ g' = ηs₁) + (e_η₂ : η₁ ≫ ηs₁ = η₂) (e_η₃ : (α ⊗ β).hom ≫ η₂ = η₃) : + (α.hom ≫ η ≫ ηs) ⊗ β.hom = η₃ := by + simp_all [MonoidalCategory.tensorHom_def'] + +theorem evalHorizontalComp_cons_cons {f f' g g' h h' i i' : C} + {α : f ≅ g} {η : g ⟶ h} {ηs : h ⟶ i} + {β : f' ≅ g'} {θ : g' ⟶ h'} {θs : h' ⟶ i'} + {ηθ : g ⊗ g' ⟶ h ⊗ h'} {ηθs : h ⊗ h' ⟶ i ⊗ i'} + {ηθ₁ : g ⊗ g' ⟶ i ⊗ i'} {ηθ₂ : f ⊗ f' ⟶ i ⊗ i'} + (e_ηθ : η ⊗ θ = ηθ) (e_ηθs : ηs ⊗ θs = ηθs) + (e_ηθ₁ : ηθ ≫ ηθs = ηθ₁) (e_ηθ₂ : (α ⊗ β).hom ≫ ηθ₁ = ηθ₂) : + (α.hom ≫ η ≫ ηs) ⊗ (β.hom ≫ θ ≫ θs) = ηθ₂ := by + simp [← e_ηθ , ← e_ηθs , ← e_ηθ₁, ← e_ηθ₂] + +end + +open Mor₂Iso + +instance : MkEvalComp MonoidalM where + mkEvalCompNilNil α β := do + let ctx ← read + let _cat := ctx.instCat + let f ← α.srcM + let g ← α.tgtM + let h ← β.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have α : Q($f ≅ $g) := α.e + have β : Q($g ≅ $h) := β.e + return q(evalComp_nil_nil $α $β) + mkEvalCompNilCons α β η ηs := do + let ctx ← read + let _cat := ctx.instCat + let f ← α.srcM + let g ← α.tgtM + let h ← β.tgtM + let i ← η.tgtM + let j ← ηs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have j : Q($ctx.C) := j.e + have α : Q($f ≅ $g) := α.e + have β : Q($g ≅ $h) := β.e + have η : Q($h ⟶ $i) := η.e.e + have ηs : Q($i ⟶ $j) := ηs.e.e + return q(evalComp_nil_cons $α $β $η $ηs) + mkEvalCompCons α η ηs θ ι e_ι := do + let ctx ← read + let _cat := ctx.instCat + let f ← α.srcM + let g ← α.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + let j ← θ.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have j : Q($ctx.C) := j.e + have α : Q($f ≅ $g) := α.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have θ : Q($i ⟶ $j) := θ.e.e + have ι : Q($h ⟶ $j) := ι.e.e + have e_ι : Q($ηs ≫ $θ = $ι) := e_ι + return q(evalComp_cons $α $η $e_ι) + +instance : MkEvalWhiskerLeft MonoidalM where + mkEvalWhiskerLeftNil f α := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← α.srcM + let h ← α.tgtM + have f_e : Q($ctx.C) := f.e + have g_e : Q($ctx.C) := g.e + have h_e : Q($ctx.C) := h.e + have α_e : Q($g_e ≅ $h_e) := α.e + return q(evalWhiskerLeft_nil $f_e $α_e) + mkEvalWhiskerLeftOfCons f α η ηs θ e_θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← α.srcM + let h ← α.tgtM + let i ← η.tgtM + let j ← ηs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have j : Q($ctx.C) := j.e + have α : Q($g ≅ $h) := α.e + have η : Q($h ⟶ $i) := η.e.e + have ηs : Q($i ⟶ $j) := ηs.e.e + have θ : Q($f ⊗ $i ⟶ $f ⊗ $j) := θ.e.e + have e_θ : Q($f ◁ $ηs = $θ) := e_θ + return q(evalWhiskerLeft_of_cons $α $η $e_θ) + mkEvalWhiskerLeftComp f g η η₁ η₂ η₃ η₄ e_η₁ e_η₂ e_η₃ e_η₄ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let h ← η.srcM + let i ← η.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have η : Q($h ⟶ $i) := η.e.e + have η₁ : Q($g ⊗ $h ⟶ $g ⊗ $i) := η₁.e.e + have η₂ : Q($f ⊗ $g ⊗ $h ⟶ $f ⊗ $g ⊗ $i) := η₂.e.e + have η₃ : Q($f ⊗ $g ⊗ $h ⟶ ($f ⊗ $g) ⊗ $i) := η₃.e.e + have η₄ : Q(($f ⊗ $g) ⊗ $h ⟶ ($f ⊗ $g) ⊗ $i) := η₄.e.e + have e_η₁ : Q($g ◁ $η = $η₁) := e_η₁ + have e_η₂ : Q($f ◁ $η₁ = $η₂) := e_η₂ + have e_η₃ : Q($η₂ ≫ (α_ _ _ _).inv = $η₃) := e_η₃ + have e_η₄ : Q((α_ _ _ _).hom ≫ $η₃ = $η₄) := e_η₄ + return q(evalWhiskerLeft_comp $e_η₁ $e_η₂ $e_η₃ $e_η₄) + mkEvalWhiskerLeftId η η₁ η₂ e_η₁ e_η₂ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have η : Q($f ⟶ $g) := η.e.e + have η₁ : Q($f ⟶ 𝟙_ _ ⊗ $g) := η₁.e.e + have η₂ : Q(𝟙_ _ ⊗ $f ⟶ 𝟙_ _ ⊗ $g) := η₂.e.e + have e_η₁ : Q($η ≫ (λ_ _).inv = $η₁) := e_η₁ + have e_η₂ : Q((λ_ _).hom ≫ $η₁ = $η₂) := e_η₂ + return q(evalWhiskerLeft_id $e_η₁ $e_η₂) + +instance : MkEvalWhiskerRight MonoidalM where + mkEvalWhiskerRightAuxOf η h := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have η : Q($f ⟶ $g) := η.e.e + have h : Q($ctx.C) := h.e + return q(evalWhiskerRightAux_of $η $h) + mkEvalWhiskerRightAuxCons f η ηs ηs' η₁ η₂ η₃ e_ηs' e_η₁ e_η₂ e_η₃ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← η.srcM + let h ← η.tgtM + let i ← ηs.srcM + let j ← ηs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have j : Q($ctx.C) := j.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($i ⟶ $j) := ηs.e.e + have ηs' : Q($i ⊗ $f ⟶ $j ⊗ $f) := ηs'.e.e + have η₁ : Q($g ⊗ ($i ⊗ $f) ⟶ $h ⊗ ($j ⊗ $f)) := η₁.e.e + have η₂ : Q($g ⊗ ($i ⊗ $f) ⟶ ($h ⊗ $j) ⊗ $f) := η₂.e.e + have η₃ : Q(($g ⊗ $i) ⊗ $f ⟶ ($h ⊗ $j) ⊗ $f) := η₃.e.e + have e_ηs' : Q($ηs ▷ $f = $ηs') := e_ηs' + have e_η₁ : Q(((Iso.refl _).hom ≫ $η ≫ (Iso.refl _).hom) ⊗ $ηs' = $η₁) := e_η₁ + have e_η₂ : Q($η₁ ≫ (α_ _ _ _).inv = $η₂) := e_η₂ + have e_η₃ : Q((α_ _ _ _).hom ≫ $η₂ = $η₃) := e_η₃ + return q(evalWhiskerRightAux_cons $e_ηs' $e_η₁ $e_η₂ $e_η₃) + mkEvalWhiskerRightNil α h := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← α.srcM + let g ← α.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have α : Q($f ≅ $g) := α.e + return q(evalWhiskerRight_nil $α $h) + mkEvalWhiskerRightConsOfOf j α η ηs ηs₁ η₁ η₂ η₃ e_ηs₁ e_η₁ e_η₂ e_η₃ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← α.srcM + let g ← α.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have j : Q($ctx.C) := j.e + have α : Q($f ≅ $g) := α.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have ηs₁ : Q($h ⊗ $j ⟶ $i ⊗ $j) := ηs₁.e.e + have η₁ : Q($g ⊗ $j ⟶ $h ⊗ $j) := η₁.e.e + have η₂ : Q($g ⊗ $j ⟶ $i ⊗ $j) := η₂.e.e + have η₃ : Q($f ⊗ $j ⟶ $i ⊗ $j) := η₃.e.e + have e_ηs₁ : Q($ηs ▷ $j = $ηs₁) := e_ηs₁ + have e_η₁ : Q($η ▷ $j = $η₁) := e_η₁ + have e_η₂ : Q($η₁ ≫ $ηs₁ = $η₂) := e_η₂ + have e_η₃ : Q((whiskerRightIso $α $j).hom ≫ $η₂ = $η₃) := e_η₃ + return q(evalWhiskerRight_cons_of_of $e_ηs₁ $e_η₁ $e_η₂ $e_η₃) + mkEvalWhiskerRightConsWhisker f k α η ηs η₁ η₂ ηs₁ ηs₂ η₃ η₄ η₅ + e_η₁ e_η₂ e_ηs₁ e_ηs₂ e_η₃ e_η₄ e_η₅ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← α.srcM + let h ← η.srcM + let i ← η.tgtM + let j ← ηs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have j : Q($ctx.C) := j.e + have k : Q($ctx.C) := k.e + have α : Q($g ≅ $f ⊗ $h) := α.e + have η : Q($h ⟶ $i) := η.e.e + have ηs : Q($f ⊗ $i ⟶ $j) := ηs.e.e + have η₁ : Q($h ⊗ $k ⟶ $i ⊗ $k) := η₁.e.e + have η₂ : Q($f ⊗ ($h ⊗ $k) ⟶ $f ⊗ ($i ⊗ $k)) := η₂.e.e + have ηs₁ : Q(($f ⊗ $i) ⊗ $k ⟶ $j ⊗ $k) := ηs₁.e.e + have ηs₂ : Q($f ⊗ ($i ⊗ $k) ⟶ $j ⊗ $k) := ηs₂.e.e + have η₃ : Q($f ⊗ ($h ⊗ $k) ⟶ $j ⊗ $k) := η₃.e.e + have η₄ : Q(($f ⊗ $h) ⊗ $k ⟶ $j ⊗ $k) := η₄.e.e + have η₅ : Q($g ⊗ $k ⟶ $j ⊗ $k) := η₅.e.e + have e_η₁ : Q(((Iso.refl _).hom ≫ $η ≫ (Iso.refl _).hom) ▷ $k = $η₁) := e_η₁ + have e_η₂ : Q($f ◁ $η₁ = $η₂) := e_η₂ + have e_ηs₁ : Q($ηs ▷ $k = $ηs₁) := e_ηs₁ + have e_ηs₂ : Q((α_ _ _ _).inv ≫ $ηs₁ = $ηs₂) := e_ηs₂ + have e_η₃ : Q($η₂ ≫ $ηs₂ = $η₃) := e_η₃ + have e_η₄ : Q((α_ _ _ _).hom ≫ $η₃ = $η₄) := e_η₄ + have e_η₅ : Q((whiskerRightIso $α $k).hom ≫ $η₄ = $η₅) := e_η₅ + return q(evalWhiskerRight_cons_whisker $e_η₁ $e_η₂ $e_ηs₁ $e_ηs₂ $e_η₃ $e_η₄ $e_η₅) + mkEvalWhiskerRightComp g h η η₁ η₂ η₃ η₄ e_η₁ e_η₂ e_η₃ e_η₄ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let f' ← η.tgtM + have f : Q($ctx.C) := f.e + have f' : Q($ctx.C) := f'.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have η : Q($f ⟶ $f') := η.e.e + have η₁ : Q($f ⊗ $g ⟶ $f' ⊗ $g) := η₁.e.e + have η₂ : Q(($f ⊗ $g) ⊗ $h ⟶ ($f' ⊗ $g) ⊗ $h) := η₂.e.e + have η₃ : Q(($f ⊗ $g) ⊗ $h ⟶ $f' ⊗ ($g ⊗ $h)) := η₃.e.e + have η₄ : Q($f ⊗ ($g ⊗ $h) ⟶ $f' ⊗ ($g ⊗ $h)) := η₄.e.e + have e_η₁ : Q($η ▷ $g = $η₁) := e_η₁ + have e_η₂ : Q($η₁ ▷ $h = $η₂) := e_η₂ + have e_η₃ : Q($η₂ ≫ (α_ _ _ _).hom = $η₃) := e_η₃ + have e_η₄ : Q((α_ _ _ _).inv ≫ $η₃ = $η₄) := e_η₄ + return q(evalWhiskerRight_comp $e_η₁ $e_η₂ $e_η₃ $e_η₄) + mkEvalWhiskerRightId η η₁ η₂ e_η₁ e_η₂ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have η : Q($f ⟶ $g) := η.e.e + have η₁ : Q($f ⟶ $g ⊗ 𝟙_ _) := η₁.e.e + have η₂ : Q($f ⊗ 𝟙_ _ ⟶ $g ⊗ 𝟙_ _) := η₂.e.e + have e_η₁ : Q($η ≫ (ρ_ _).inv = $η₁) := e_η₁ + have e_η₂ : Q((ρ_ _).hom ≫ $η₁ = $η₂) := e_η₂ + return q(evalWhiskerRight_id $e_η₁ $e_η₂) + +instance : MkEvalHorizontalComp MonoidalM where + mkEvalHorizontalCompAuxOf η θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + let h ← θ.srcM + let i ← θ.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have η : Q($f ⟶ $g) := η.e.e + have θ : Q($h ⟶ $i) := θ.e.e + return q(evalHorizontalCompAux_of $η $θ) + mkEvalHorizontalCompAuxCons η ηs θ ηθ η₁ ηθ₁ ηθ₂ e_ηθ e_η₁ e_ηθ₁ e_ηθ₂ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η.srcM + let g ← η.tgtM + let f' ← ηs.srcM + let g' ← ηs.tgtM + let h ← θ.srcM + let i ← θ.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have f' : Q($ctx.C) := f'.e + have g' : Q($ctx.C) := g'.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have η : Q($f ⟶ $g) := η.e.e + have ηs : Q($f' ⟶ $g') := ηs.e.e + have θ : Q($h ⟶ $i) := θ.e.e + have ηθ : Q($f' ⊗ $h ⟶ $g' ⊗ $i) := ηθ.e.e + have η₁ : Q($f ⊗ ($f' ⊗ $h) ⟶ $g ⊗ ($g' ⊗ $i)) := η₁.e.e + have ηθ₁ : Q($f ⊗ ($f' ⊗ $h) ⟶ ($g ⊗ $g') ⊗ $i) := ηθ₁.e.e + have ηθ₂ : Q(($f ⊗ $f') ⊗ $h ⟶ ($g ⊗ $g') ⊗ $i) := ηθ₂.e.e + have e_ηθ : Q($ηs ⊗ $θ = $ηθ) := e_ηθ + have e_η₁ : Q(((Iso.refl _).hom ≫ $η ≫ (Iso.refl _).hom) ⊗ $ηθ = $η₁) := e_η₁ + have e_ηθ₁ : Q($η₁ ≫ (α_ _ _ _).inv = $ηθ₁) := e_ηθ₁ + have e_ηθ₂ : Q((α_ _ _ _).hom ≫ $ηθ₁ = $ηθ₂) := e_ηθ₂ + return q(evalHorizontalCompAux_cons $e_ηθ $e_η₁ $e_ηθ₁ $e_ηθ₂) + mkEvalHorizontalCompAux'Whisker f η θ ηθ η₁ η₂ η₃ e_ηθ e_η₁ e_η₂ e_η₃ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← η.srcM + let h ← η.tgtM + let f' ← θ.srcM + let g' ← θ.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have f' : Q($ctx.C) := f'.e + have g' : Q($ctx.C) := g'.e + have η : Q($g ⟶ $h) := η.e.e + have θ : Q($f' ⟶ $g') := θ.e.e + have ηθ : Q($g ⊗ $f' ⟶ $h ⊗ $g') := ηθ.e.e + have η₁ : Q($f ⊗ ($g ⊗ $f') ⟶ $f ⊗ ($h ⊗ $g')) := η₁.e.e + have η₂ : Q($f ⊗ ($g ⊗ $f') ⟶ ($f ⊗ $h) ⊗ $g') := η₂.e.e + have η₃ : Q(($f ⊗ $g) ⊗ $f' ⟶ ($f ⊗ $h) ⊗ $g') := η₃.e.e + have e_ηθ : Q($η ⊗ $θ = $ηθ) := e_ηθ + have e_η₁ : Q($f ◁ $ηθ = $η₁) := e_η₁ + have e_η₂ : Q($η₁ ≫ (α_ _ _ _).inv = $η₂) := e_η₂ + have e_η₃ : Q((α_ _ _ _).hom ≫ $η₂ = $η₃) := e_η₃ + return q(evalHorizontalCompAux'_whisker $e_ηθ $e_η₁ $e_η₂ $e_η₃) + mkEvalHorizontalCompAux'OfWhisker f η θ η₁ ηθ ηθ₁ ηθ₂ e_η₁ e_ηθ e_ηθ₁ e_ηθ₂ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← η.srcM + let h ← η.tgtM + let f' ← θ.srcM + let g' ← θ.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have f' : Q($ctx.C) := f'.e + have g' : Q($ctx.C) := g'.e + have η : Q($g ⟶ $h) := η.e.e + have θ : Q($f' ⟶ $g') := θ.e.e + have η₁ : Q($g ⊗ $f ⟶ $h ⊗ $f) := η₁.e.e + have ηθ : Q(($g ⊗ $f) ⊗ $f' ⟶ ($h ⊗ $f) ⊗ $g') := ηθ.e.e + have ηθ₁ : Q(($g ⊗ $f) ⊗ $f' ⟶ $h ⊗ ($f ⊗ $g')) := ηθ₁.e.e + have ηθ₂ : Q($g ⊗ ($f ⊗ $f') ⟶ $h ⊗ ($f ⊗ $g')) := ηθ₂.e.e + have e_η₁ : Q($η ▷ $f = $η₁) := e_η₁ + have e_ηθ : Q($η₁ ⊗ ((Iso.refl _).hom ≫ $θ ≫ (Iso.refl _).hom) = $ηθ) := e_ηθ + have e_ηθ₁ : Q($ηθ ≫ (α_ _ _ _).hom = $ηθ₁) := e_ηθ₁ + have e_ηθ₂ : Q((α_ _ _ _).inv ≫ $ηθ₁ = $ηθ₂) := e_ηθ₂ + return q(evalHorizontalCompAux'_of_whisker $e_η₁ $e_ηθ $e_ηθ₁ $e_ηθ₂) + mkEvalHorizontalCompNilNil α β := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← α.srcM + let g ← α.tgtM + let h ← β.srcM + let i ← β.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have α : Q($f ≅ $g) := α.e + have β : Q($h ≅ $i) := β.e + return q(evalHorizontalComp_nil_nil $α $β) + mkEvalHorizontalCompNilCons α β η ηs η₁ ηs₁ η₂ η₃ e_η₁ e_ηs₁ e_η₂ e_η₃ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← α.srcM + let g ← α.tgtM + let f' ← β.srcM + let g' ← β.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have f' : Q($ctx.C) := f'.e + have g' : Q($ctx.C) := g'.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have α : Q($f ≅ $g) := α.e + have β : Q($f' ≅ $g') := β.e + have η : Q($g' ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have η₁ : Q($g ⊗ $g' ⟶ $g ⊗ $h) := η₁.e.e + have ηs₁ : Q($g ⊗ $h ⟶ $g ⊗ $i) := ηs₁.e.e + have η₂ : Q($g ⊗ $g' ⟶ $g ⊗ $i) := η₂.e.e + have η₃ : Q($f ⊗ $f' ⟶ $g ⊗ $i) := η₃.e.e + have e_η₁ : Q($g ◁ ((Iso.refl _).hom ≫ $η ≫ (Iso.refl _).hom) = $η₁) := e_η₁ + have e_ηs₁ : Q($g ◁ $ηs = $ηs₁) := e_ηs₁ + have e_η₂ : Q($η₁ ≫ $ηs₁ = $η₂) := e_η₂ + have e_η₃ : Q(($α ⊗ $β).hom ≫ $η₂ = $η₃) := e_η₃ + return q(evalHorizontalComp_nil_cons $e_η₁ $e_ηs₁ $e_η₂ $e_η₃) + mkEvalHorizontalCompConsNil α β η ηs η₁ ηs₁ η₂ η₃ e_η₁ e_ηs₁ e_η₂ e_η₃ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← α.srcM + let g ← α.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + let f' ← β.srcM + let g' ← β.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have f' : Q($ctx.C) := f'.e + have g' : Q($ctx.C) := g'.e + have α : Q($f ≅ $g) := α.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have β : Q($f' ≅ $g') := β.e + have η₁ : Q($g ⊗ $g' ⟶ $h ⊗ $g') := η₁.e.e + have ηs₁ : Q($h ⊗ $g' ⟶ $i ⊗ $g') := ηs₁.e.e + have η₂ : Q($g ⊗ $g' ⟶ $i ⊗ $g') := η₂.e.e + have η₃ : Q($f ⊗ $f' ⟶ $i ⊗ $g') := η₃.e.e + have e_η₁ : Q(((Iso.refl _).hom ≫ $η ≫ (Iso.refl _).hom) ▷ $g' = $η₁) := e_η₁ + have e_ηs₁ : Q($ηs ▷ $g' = $ηs₁) := e_ηs₁ + have e_η₂ : Q($η₁ ≫ $ηs₁ = $η₂) := e_η₂ + have e_η₃ : Q(($α ⊗ $β).hom ≫ $η₂ = $η₃) := e_η₃ + return q(evalHorizontalComp_cons_nil $e_η₁ $e_ηs₁ $e_η₂ $e_η₃) + mkEvalHorizontalCompConsCons α β η θ ηs θs ηθ ηθs ηθ₁ ηθ₂ e_ηθ e_ηθs e_ηθ₁ e_ηθ₂ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← α.srcM + let g ← α.tgtM + let h ← η.tgtM + let i ← ηs.tgtM + let f' ← β.srcM + let g' ← β.tgtM + let h' ← θ.tgtM + let i' ← θs.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have f' : Q($ctx.C) := f'.e + have g' : Q($ctx.C) := g'.e + have h' : Q($ctx.C) := h'.e + have i' : Q($ctx.C) := i'.e + have α : Q($f ≅ $g) := α.e + have η : Q($g ⟶ $h) := η.e.e + have ηs : Q($h ⟶ $i) := ηs.e.e + have β : Q($f' ≅ $g') := β.e + have θ : Q($g' ⟶ $h') := θ.e.e + have θs : Q($h' ⟶ $i') := θs.e.e + have ηθ : Q($g ⊗ $g' ⟶ $h ⊗ $h') := ηθ.e.e + have ηθs : Q($h ⊗ $h' ⟶ $i ⊗ $i') := ηθs.e.e + have ηθ₁ : Q($g ⊗ $g' ⟶ $i ⊗ $i') := ηθ₁.e.e + have ηθ₂ : Q($f ⊗ $f' ⟶ $i ⊗ $i') := ηθ₂.e.e + have e_ηθ : Q($η ⊗ $θ = $ηθ) := e_ηθ + have e_ηθs : Q($ηs ⊗ $θs = $ηθs) := e_ηθs + have e_ηθ₁ : Q($ηθ ≫ $ηθs = $ηθ₁) := e_ηθ₁ + have e_ηθ₂ : Q(($α ⊗ $β).hom ≫ $ηθ₁ = $ηθ₂) := e_ηθ₂ + return q(evalHorizontalComp_cons_cons $e_ηθ $e_ηθs $e_ηθ₁ $e_ηθ₂) + +instance : MkEval MonoidalM where + mkEvalComp η θ η' θ' ι e_η e_θ e_ηθ := do + let ctx ← read + let _cat := ctx.instCat + let f ← η'.srcM + let g ← η'.tgtM + let h ← θ'.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have θ : Q($g ⟶ $h) := θ.e + have θ' : Q($g ⟶ $h) := θ'.e.e + have ι : Q($f ⟶ $h) := ι.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($θ = $θ') := e_θ + have e_ηθ : Q($η' ≫ $θ' = $ι) := e_ηθ + return q(eval_comp $e_η $e_θ $e_ηθ) + mkEvalWhiskerLeft f η η' θ e_η e_θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let g ← η'.srcM + let h ← η'.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have η : Q($g ⟶ $h) := η.e + have η' : Q($g ⟶ $h) := η'.e.e + have θ : Q($f ⊗ $g ⟶ $f ⊗ $h) := θ.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($f ◁ $η' = $θ) := e_θ + return q(eval_whiskerLeft $e_η $e_θ) + mkEvalWhiskerRight η h η' θ e_η e_θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η'.srcM + let g ← η'.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have θ : Q($f ⊗ $h ⟶ $g ⊗ $h) := θ.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($η' ▷ $h = $θ) := e_θ + return q(eval_whiskerRight $e_η $e_θ) + mkEvalHorizontalComp η θ η' θ' ι e_η e_θ e_ι := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let f ← η'.srcM + let g ← η'.tgtM + let h ← θ'.srcM + let i ← θ'.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have θ : Q($h ⟶ $i) := θ.e + have θ' : Q($h ⟶ $i) := θ'.e.e + have ι : Q($f ⊗ $h ⟶ $g ⊗ $i) := ι.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($θ = $θ') := e_θ + have e_ι : Q($η' ⊗ $θ' = $ι) := e_ι + return q(eval_tensorHom $e_η $e_θ $e_ι) + mkEvalOf η := do + let ctx ← read + let _cat := ctx.instCat + let f := η.src + let g := η.tgt + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have η : Q($f ⟶ $g) := η.e + return q(eval_of $η) + mkEvalMonoidalComp η θ α η' θ' αθ ηαθ e_η e_θ e_αθ e_ηαθ := do + let ctx ← read + let _cat := ctx.instCat + let f ← η'.srcM + let g ← η'.tgtM + let h ← α.tgtM + let i ← θ'.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have i : Q($ctx.C) := i.e + have η : Q($f ⟶ $g) := η.e + have η' : Q($f ⟶ $g) := η'.e.e + have α : Q($g ≅ $h) := α.e + have θ : Q($h ⟶ $i) := θ.e + have θ' : Q($h ⟶ $i) := θ'.e.e + have αθ : Q($g ⟶ $i) := αθ.e.e + have ηαθ : Q($f ⟶ $i) := ηαθ.e.e + have e_η : Q($η = $η') := e_η + have e_θ : Q($θ = $θ') := e_θ + have e_αθ : Q(Iso.hom $α ≫ $θ' = $αθ) := e_αθ + have e_ηαθ : Q($η' ≫ $αθ = $ηαθ) := e_ηαθ + return q(eval_monoidalComp $e_η $e_θ $e_αθ $e_ηαθ) + +instance : MonadNormalExpr MonoidalM where + whiskerRightM η h := do + return .whisker (← MonadMor₂.whiskerRightM η.e (.of h)) η h + hConsM η θ := do + return .cons (← MonadMor₂.horizontalCompM η.e θ.e) η θ + whiskerLeftM f η := do + return .whisker (← MonadMor₂.whiskerLeftM (.of f) η.e) f η + nilM α := do + return .nil (← MonadMor₂.homM α) α + consM α η ηs := do + return .cons (← MonadMor₂.comp₂M (← MonadMor₂.homM α) (← MonadMor₂.comp₂M η.e ηs.e)) α η ηs + +instance : MkMor₂ MonoidalM where + ofExpr := Mor₂OfExpr + +end Mathlib.Tactic.Monoidal diff --git a/Mathlib/Tactic/CategoryTheory/Monoidal/PureCoherence.lean b/Mathlib/Tactic/CategoryTheory/Monoidal/PureCoherence.lean new file mode 100644 index 0000000000000..56c83c25a1459 --- /dev/null +++ b/Mathlib/Tactic/CategoryTheory/Monoidal/PureCoherence.lean @@ -0,0 +1,277 @@ +/- +Copyright (c) 2024 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.Tactic.CategoryTheory.Coherence.PureCoherence +import Mathlib.Tactic.CategoryTheory.Monoidal.Datatypes + +/-! +# Coherence tactic for monoidal categories + +We provide a `monoidal_coherence` tactic, +which proves that any two morphisms (with the same source and target) +in a monoidal category which are built out of associators and unitors +are equal. + +-/ + +open Lean Meta Elab Qq +open CategoryTheory Mathlib.Tactic.BicategoryLike MonoidalCategory + +namespace Mathlib.Tactic.Monoidal + +section + +universe v u + +variable {C : Type u} [Category.{v} C] [MonoidalCategory C] + +local infixr:81 " ◁ " => MonoidalCategory.whiskerLeftIso +local infixl:81 " ▷ " => MonoidalCategory.whiskerRightIso + +/-- The composition of the normalizing isomorphisms `η_f : p ⊗ f ≅ pf` and `η_g : pf ⊗ g ≅ pfg`. -/ +abbrev normalizeIsoComp {p f g pf pfg : C} (η_f : p ⊗ f ≅ pf) (η_g : pf ⊗ g ≅ pfg) := + (α_ _ _ _).symm ≪≫ whiskerRightIso η_f g ≪≫ η_g + +theorem naturality_associator {p f g h pf pfg pfgh : C} + (η_f : p ⊗ f ≅ pf) (η_g : pf ⊗ g ≅ pfg) (η_h : pfg ⊗ h ≅ pfgh) : + p ◁ (α_ f g h) ≪≫ normalizeIsoComp η_f (normalizeIsoComp η_g η_h) = + normalizeIsoComp (normalizeIsoComp η_f η_g) η_h := + Iso.ext (by simp) + +theorem naturality_leftUnitor {p f pf : C} (η_f : p ⊗ f ≅ pf) : + p ◁ (λ_ f) ≪≫ η_f = normalizeIsoComp (ρ_ p) η_f := + Iso.ext (by simp) + +theorem naturality_rightUnitor {p f pf : C} (η_f : p ⊗ f ≅ pf) : + p ◁ (ρ_ f) ≪≫ η_f = normalizeIsoComp η_f (ρ_ pf) := + Iso.ext (by simp) + +theorem naturality_id {p f pf : C} (η_f : p ⊗ f ≅ pf) : + p ◁ Iso.refl f ≪≫ η_f = η_f := by + simp + +theorem naturality_comp {p f g h pf : C} {η : f ≅ g} {θ : g ≅ h} + (η_f : p ⊗ f ≅ pf) (η_g : p ⊗ g ≅ pf) (η_h : p ⊗ h ≅ pf) + (ih_η : p ◁ η ≪≫ η_g = η_f) (ih_θ : p ◁ θ ≪≫ η_h = η_g) : + p ◁ (η ≪≫ θ) ≪≫ η_h = η_f := by + simp_all + +theorem naturality_whiskerLeft {p f g h pf pfg : C} {η : g ≅ h} + (η_f : p ⊗ f ≅ pf) (η_fg : pf ⊗ g ≅ pfg) (η_fh : (pf ⊗ h) ≅ pfg) + (ih_η : pf ◁ η ≪≫ η_fh = η_fg) : + p ◁ (f ◁ η) ≪≫ normalizeIsoComp η_f η_fh = normalizeIsoComp η_f η_fg := by + rw [← ih_η] + apply Iso.ext + simp [← whisker_exchange_assoc] + +theorem naturality_whiskerRight {p f g h pf pfh : C} {η : f ≅ g} + (η_f : p ⊗ f ≅ pf) (η_g : p ⊗ g ≅ pf) (η_fh : (pf ⊗ h) ≅ pfh) + (ih_η : p ◁ η ≪≫ η_g = η_f) : + p ◁ (η ▷ h) ≪≫ normalizeIsoComp η_g η_fh = normalizeIsoComp η_f η_fh := by + rw [← ih_η] + apply Iso.ext + simp + +theorem naturality_tensorHom {p f₁ g₁ f₂ g₂ pf₁ pf₁f₂ : C} {η : f₁ ≅ g₁} {θ : f₂ ≅ g₂} + (η_f₁ : p ⊗ f₁ ≅ pf₁) (η_g₁ : p ⊗ g₁ ≅ pf₁) (η_f₂ : pf₁ ⊗ f₂ ≅ pf₁f₂) (η_g₂ : pf₁ ⊗ g₂ ≅ pf₁f₂) + (ih_η : p ◁ η ≪≫ η_g₁ = η_f₁) + (ih_θ : pf₁ ◁ θ ≪≫ η_g₂ = η_f₂) : + p ◁ (η ⊗ θ) ≪≫ normalizeIsoComp η_g₁ η_g₂ = normalizeIsoComp η_f₁ η_f₂ := by + rw [tensorIso_def] + apply naturality_comp + · apply naturality_whiskerRight _ _ _ ih_η + · apply naturality_whiskerLeft _ _ _ ih_θ + +theorem naturality_inv {p f g pf : C} {η : f ≅ g} + (η_f : p ⊗ f ≅ pf) (η_g : p ⊗ g ≅ pf) (ih : p ◁ η ≪≫ η_g = η_f) : + p ◁ η.symm ≪≫ η_f = η_g := by + rw [← ih] + apply Iso.ext + simp + +instance : MonadNormalizeNaturality MonoidalM where + mkNaturalityAssociator p pf pfg pfgh f g h η_f η_g η_h := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have pf : Q($ctx.C) := pf.e.e + have pfg : Q($ctx.C) := pfg.e.e + have pfgh : Q($ctx.C) := pfgh.e.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + have η_g : Q($pf ⊗ $g ≅ $pfg) := η_g.e + have η_h : Q($pfg ⊗ $h ≅ $pfgh) := η_h.e + return q(naturality_associator $η_f $η_g $η_h) + mkNaturalityLeftUnitor p pf f η_f := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have pf : Q($ctx.C) := pf.e.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + return q(naturality_leftUnitor $η_f) + mkNaturalityRightUnitor p pf f η_f := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have pf : Q($ctx.C) := pf.e.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + return q(naturality_rightUnitor $η_f) + mkNaturalityId p pf f η_f := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have pf : Q($ctx.C) := pf.e.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + return q(naturality_id $η_f) + mkNaturalityComp p pf f g h η θ η_f η_g η_h ih_η ih_θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have pf : Q($ctx.C) := pf.e.e + have η : Q($f ≅ $g) := η.e + have θ : Q($g ≅ $h) := θ.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + have η_g : Q($p ⊗ $g ≅ $pf) := η_g.e + have η_h : Q($p ⊗ $h ≅ $pf) := η_h.e + have ih_η : Q($p ◁ $η ≪≫ $η_g = $η_f) := ih_η + have ih_θ : Q($p ◁ $θ ≪≫ $η_h = $η_g) := ih_θ + return q(naturality_comp $η_f $η_g $η_h $ih_η $ih_θ) + mkNaturalityWhiskerLeft p pf pfg f g h η η_f η_fg η_fh ih_η := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have pf : Q($ctx.C) := pf.e.e + have pfg : Q($ctx.C) := pfg.e.e + have η : Q($g ≅ $h) := η.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + have η_fg : Q($pf ⊗ $g ≅ $pfg) := η_fg.e + have η_fh : Q($pf ⊗ $h ≅ $pfg) := η_fh.e + have ih_η : Q($pf ◁ $η ≪≫ $η_fh = $η_fg) := ih_η + return q(naturality_whiskerLeft $η_f $η_fg $η_fh $ih_η) + mkNaturalityWhiskerRight p pf pfh f g h η η_f η_g η_fh ih_η := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have h : Q($ctx.C) := h.e + have pf : Q($ctx.C) := pf.e.e + have pfh : Q($ctx.C) := pfh.e.e + have η : Q($f ≅ $g) := η.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + have η_g : Q($p ⊗ $g ≅ $pf) := η_g.e + have η_fh : Q($pf ⊗ $h ≅ $pfh) := η_fh.e + have ih_η : Q($p ◁ $η ≪≫ $η_g = $η_f) := ih_η + return q(naturality_whiskerRight $η_f $η_g $η_fh $ih_η) + mkNaturalityHorizontalComp p pf₁ pf₁f₂ f₁ g₁ f₂ g₂ η θ η_f₁ η_g₁ η_f₂ η_g₂ ih_η ih_θ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f₁ : Q($ctx.C) := f₁.e + have g₁ : Q($ctx.C) := g₁.e + have f₂ : Q($ctx.C) := f₂.e + have g₂ : Q($ctx.C) := g₂.e + have pf₁ : Q($ctx.C) := pf₁.e.e + have pf₁f₂ : Q($ctx.C) := pf₁f₂.e.e + have η : Q($f₁ ≅ $g₁) := η.e + have θ : Q($f₂ ≅ $g₂) := θ.e + have η_f₁ : Q($p ⊗ $f₁ ≅ $pf₁) := η_f₁.e + have η_g₁ : Q($p ⊗ $g₁ ≅ $pf₁) := η_g₁.e + have η_f₂ : Q($pf₁ ⊗ $f₂ ≅ $pf₁f₂) := η_f₂.e + have η_g₂ : Q($pf₁ ⊗ $g₂ ≅ $pf₁f₂) := η_g₂.e + have ih_η : Q($p ◁ $η ≪≫ $η_g₁ = $η_f₁) := ih_η + have ih_θ : Q($pf₁ ◁ $θ ≪≫ $η_g₂ = $η_f₂) := ih_θ + return q(naturality_tensorHom $η_f₁ $η_g₁ $η_f₂ $η_g₂ $ih_η $ih_θ) + mkNaturalityInv p pf f g η η_f η_g ih := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + have p : Q($ctx.C) := p.e.e + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have pf : Q($ctx.C) := pf.e.e + have η : Q($f ≅ $g) := η.e + have η_f : Q($p ⊗ $f ≅ $pf) := η_f.e + have η_g : Q($p ⊗ $g ≅ $pf) := η_g.e + have ih : Q($p ◁ $η ≪≫ $η_g = $η_f) := ih + return q(naturality_inv $η_f $η_g $ih) + +theorem of_normalize_eq {f g f' : C} {η θ : f ≅ g} (η_f : 𝟙_ C ⊗ f ≅ f') (η_g : 𝟙_ C ⊗ g ≅ f') + (h_η : 𝟙_ C ◁ η ≪≫ η_g = η_f) + (h_θ : 𝟙_ C ◁ θ ≪≫ η_g = η_f) : η = θ := by + apply Iso.ext + calc + η.hom = (λ_ f).inv ≫ η_f.hom ≫ η_g.inv ≫ (λ_ g).hom := by + simp [← reassoc_of% (congrArg Iso.hom h_η)] + _ = θ.hom := by + simp [← reassoc_of% (congrArg Iso.hom h_θ)] + +theorem mk_eq_of_naturality {f g f' : C} {η θ : f ⟶ g} {η' θ' : f ≅ g} + (η_f : 𝟙_ C ⊗ f ≅ f') (η_g : 𝟙_ C ⊗ g ≅ f') + (η_hom : η'.hom = η) (Θ_hom : θ'.hom = θ) + (Hη : whiskerLeftIso (𝟙_ C) η' ≪≫ η_g = η_f) + (Hθ : whiskerLeftIso (𝟙_ C) θ' ≪≫ η_g = η_f) : η = θ := + calc + η = η'.hom := η_hom.symm + _ = (λ_ f).inv ≫ η_f.hom ≫ η_g.inv ≫ (λ_ g).hom := by + simp [← reassoc_of% (congrArg Iso.hom Hη)] + _ = θ'.hom := by + simp [← reassoc_of% (congrArg Iso.hom Hθ)] + _ = θ := Θ_hom + +end + +instance : MkEqOfNaturality MonoidalM where + mkEqOfNaturality η θ ηIso θIso η_f η_g Hη Hθ := do + let ctx ← read + let .some _monoidal := ctx.instMonoidal? | synthMonoidalError + let η' := ηIso.e + let θ' := θIso.e + let f ← η'.srcM + let g ← η'.tgtM + let f' ← η_f.tgtM + have f : Q($ctx.C) := f.e + have g : Q($ctx.C) := g.e + have f' : Q($ctx.C) := f'.e + have η : Q($f ⟶ $g) := η + have θ : Q($f ⟶ $g) := θ + have η'_e : Q($f ≅ $g) := η'.e + have θ'_e : Q($f ≅ $g) := θ'.e + have η_f : Q(tensorUnit ⊗ $f ≅ $f') := η_f.e + have η_g : Q(tensorUnit ⊗ $g ≅ $f') := η_g.e + have η_hom : Q(Iso.hom $η'_e = $η) := ηIso.eq + have Θ_hom : Q(Iso.hom $θ'_e = $θ) := θIso.eq + have Hη : Q(whiskerLeftIso tensorUnit $η'_e ≪≫ $η_g = $η_f) := Hη + have Hθ : Q(whiskerLeftIso tensorUnit $θ'_e ≪≫ $η_g = $η_f) := Hθ + return q(mk_eq_of_naturality $η_f $η_g $η_hom $Θ_hom $Hη $Hθ) + +open Elab.Tactic + +/-- Close the goal of the form `η = θ`, where `η` and `θ` are 2-isomorphisms made up only of +associators, unitors, and identities. +```lean +example {C : Type} [Category C] [MonoidalCategory C] : + (λ_ (𝟙_ C)).hom = (ρ_ (𝟙_ C)).hom := by + monoidal_coherence +``` +-/ +def pureCoherence (mvarId : MVarId) : MetaM (List MVarId) := + BicategoryLike.pureCoherence Monoidal.Context `monoidal mvarId + +@[inherit_doc pureCoherence] +elab "monoidal_coherence" : tactic => withMainContext do + replaceMainGoal <| ← Monoidal.pureCoherence <| ← getMainGoal + +end Mathlib.Tactic.Monoidal diff --git a/Mathlib/Tactic/Widget/StringDiagram.lean b/Mathlib/Tactic/Widget/StringDiagram.lean index d5fb48b69c1e5..9ba22761bcd5e 100644 --- a/Mathlib/Tactic/Widget/StringDiagram.lean +++ b/Mathlib/Tactic/Widget/StringDiagram.lean @@ -7,7 +7,8 @@ import ProofWidgets.Component.PenroseDiagram import ProofWidgets.Component.Panel.Basic import ProofWidgets.Presentation.Expr import ProofWidgets.Component.HtmlDisplay -import Mathlib.Tactic.CategoryTheory.Monoidal +import Mathlib.Tactic.CategoryTheory.Bicategory.Normalize +import Mathlib.Tactic.CategoryTheory.Monoidal.Normalize /-! # String Diagram Widget @@ -62,7 +63,7 @@ namespace Mathlib.Tactic open Lean Meta Elab open CategoryTheory -open Mathlib.Tactic.Monoidal +open BicategoryLike namespace Widget.StringDiagram @@ -104,15 +105,15 @@ def Node.e : Node → Expr /-- The domain of the 2-morphism associated with a node as a list (the first component is the node itself). -/ -def Node.srcList : Node → MetaM (List (Node × Atom₁)) - | Node.atom n => return (← n.atom.src).toList.map (fun f ↦ (.atom n, f)) - | Node.id n => return [(.id n, n.id)] +def Node.srcList : Node → List (Node × Atom₁) + | Node.atom n => n.atom.src.toList.map (fun f ↦ (.atom n, f)) + | Node.id n => [(.id n, n.id)] /-- The codomain of the 2-morphism associated with a node as a list (the first component is the node itself). -/ -def Node.tarList : Node → MetaM (List (Node × Atom₁)) - | Node.atom n => return (← n.atom.tgt).toList.map (fun f ↦ (.atom n, f)) - | Node.id n => return [(.id n, n.id)] +def Node.tarList : Node → List (Node × Atom₁) + | Node.atom n => n.atom.tgt.toList.map (fun f ↦ (.atom n, f)) + | Node.id n => [(.id n, n.id)] /-- The vertical position of a node in a string diagram. -/ def Node.vPos : Node → ℕ @@ -129,10 +130,6 @@ def Node.hPosTar : Node → ℕ | Node.atom n => n.hPosTar | Node.id n => n.hPosTar -/-- The list of nodes at the top of a string diagram. -/ -def topNodes (η : WhiskerLeftExpr) : MetaM (List Node) := do - return (← η.src).toList.enum.map (fun (i, f) => .id ⟨0, i, i, f⟩) - /-- Strings in a string diagram. -/ structure Strand : Type where /-- The horizontal position of the strand in the string diagram. -/ @@ -150,62 +147,79 @@ def Strand.vPos (s : Strand) : ℕ := end Widget.StringDiagram -namespace Monoidal +namespace BicategoryLike open Widget.StringDiagram /-- The list of nodes associated with a 2-morphism. The position is counted from the specified natural numbers. -/ -def WhiskerRightExpr.nodes (v h₁ h₂ : ℕ) : WhiskerRightExpr → MetaM (List Node) - | WhiskerRightExpr.of η => do - return [.atom ⟨v, h₁, h₂, η⟩] - | WhiskerRightExpr.whisker η f => do - let ηs ← η.nodes v h₁ h₂ - let k₁ := (← ηs.mapM (fun n ↦ n.srcList)).join.length - let k₂ := (← ηs.mapM (fun n ↦ n.tarList)).join.length +def WhiskerRight.nodes (v h₁ h₂ : ℕ) : WhiskerRight → List Node + | WhiskerRight.of η => [.atom ⟨v, h₁, h₂, η⟩] + | WhiskerRight.whisker _ η f => + let ηs := η.nodes v h₁ h₂ + let k₁ := (ηs.map (fun n ↦ n.srcList)).join.length + let k₂ := (ηs.map (fun n ↦ n.tarList)).join.length let s : Node := .id ⟨v, h₁ + k₁, h₂ + k₂, f⟩ - return ηs ++ [s] + ηs ++ [s] /-- The list of nodes associated with a 2-morphism. The position is counted from the specified natural numbers. -/ -def WhiskerLeftExpr.nodes (v h₁ h₂ : ℕ) : WhiskerLeftExpr → MetaM (List Node) - | WhiskerLeftExpr.of η => η.nodes v h₁ h₂ - | WhiskerLeftExpr.whisker f η => do +def HorizontalComp.nodes (v h₁ h₂ : ℕ) : HorizontalComp → List Node + | HorizontalComp.of η => η.nodes v h₁ h₂ + | HorizontalComp.cons _ η ηs => + let s₁ := η.nodes v h₁ h₂ + let k₁ := (s₁.map (fun n ↦ n.srcList)).join.length + let k₂ := (s₁.map (fun n ↦ n.tarList)).join.length + let s₂ := ηs.nodes v (h₁ + k₁) (h₂ + k₂) + s₁ ++ s₂ + +/-- The list of nodes associated with a 2-morphism. The position is counted from the +specified natural numbers. -/ +def WhiskerLeft.nodes (v h₁ h₂ : ℕ) : WhiskerLeft → List Node + | WhiskerLeft.of η => η.nodes v h₁ h₂ + | WhiskerLeft.whisker _ f η => let s : Node := .id ⟨v, h₁, h₂, f⟩ - let ss ← η.nodes v (h₁ + 1) (h₂ + 1) - return s :: ss + let ss := η.nodes v (h₁ + 1) (h₂ + 1) + s :: ss + +variable {ρ : Type} [Context ρ] [MonadMor₁ (CoherenceM ρ)] + +/-- The list of nodes at the top of a string diagram. -/ +def topNodes (η : WhiskerLeft) : CoherenceM ρ (List Node) := do + return (← η.srcM).toList.enum.map (fun (i, f) => .id ⟨0, i, i, f⟩) /-- The list of nodes at the top of a string diagram. The position is counted from the specified natural number. -/ -def NormalExpr.nodesAux (v : ℕ) : NormalExpr → MetaM (List (List Node)) - | NormalExpr.nil α => return [(α.src).toList.enum.map (fun (i, f) => .id ⟨v, i, i, f⟩)] - | NormalExpr.cons _ η ηs => do - let s₁ ← η.nodes v 0 0 +def NormalExpr.nodesAux (v : ℕ) : NormalExpr → CoherenceM ρ (List (List Node)) + | NormalExpr.nil _ α => return [(← α.srcM).toList.enum.map (fun (i, f) => .id ⟨v, i, i, f⟩)] + | NormalExpr.cons _ _ η ηs => do + let s₁ := η.nodes v 0 0 let s₂ ← ηs.nodesAux (v + 1) return s₁ :: s₂ /-- The list of nodes associated with a 2-morphism. -/ -def NormalExpr.nodes (e : NormalExpr) : MetaM (List (List Node)) := do +def NormalExpr.nodes (e : NormalExpr) : CoherenceM ρ (List (List Node)) := match e with - | NormalExpr.nil _ => return [] - | NormalExpr.cons _ η _ => return (← topNodes η) :: (← e.nodesAux 1) + | NormalExpr.nil _ _ => return [] + | NormalExpr.cons _ _ η _ => return (← topNodes η) :: (← e.nodesAux 1) /-- `pairs [a, b, c, d]` is `[(a, b), (b, c), (c, d)]`. -/ def pairs {α : Type} : List α → List (α × α) := fun l => l.zip (l.drop 1) /-- The list of strands associated with a 2-morphism. -/ -def NormalExpr.strands (e : NormalExpr) : MetaM (List (List Strand)) := do +def NormalExpr.strands (e : NormalExpr) : CoherenceM ρ (List (List Strand)) := do let l ← e.nodes (pairs l).mapM fun (x, y) ↦ do - let xs := (← x.mapM (fun n ↦ n.tarList)).join - let ys := (← y.mapM (fun n ↦ n.srcList)).join + let xs := (x.map (fun n ↦ n.tarList)).join + let ys := (y.map (fun n ↦ n.srcList)).join + -- sanity check if xs.length ≠ ys.length then throwError "The number of the start and end points of a string does not match." (xs.zip ys).enum.mapM fun (k, (n₁, f₁), (n₂, _)) => do return ⟨n₁.hPosTar + k, n₁, n₂, f₁⟩ -end Monoidal +end BicategoryLike namespace Widget.StringDiagram @@ -249,9 +263,8 @@ def addConstructor (tp : String) (v : PenroseVar) (nm : String) (vs : List Penro open scoped Jsx in /-- Construct a string diagram from a Penrose `sub`stance program and expressions `embeds` to display as labels in the diagram. -/ -def mkStringDiagram (e : NormalExpr) : DiagramBuilderM PUnit := do - let nodes ← e.nodes - let strands ← e.strands +def mkStringDiagram (nodes : List (List Node)) (strands : List (List Strand)) : + DiagramBuilderM PUnit := do /- Add 2-morphisms. -/ for x in nodes.join do match x with @@ -280,22 +293,59 @@ def dsl := def sty := include_str ".."/".."/".."/"widget"/"src"/"penrose"/"monoidal.sty" -open scoped Jsx in -/-- Construct a string diagram from the expression of a 2-morphism. -/ -def fromExpr (e : Expr) : MonoidalM Html := do - let e' := (← eval e).expr - DiagramBuilderM.run do - mkStringDiagram e' - trace[string_diagram] "Penrose substance: \n{(← get).sub}" - match ← DiagramBuilderM.buildDiagram dsl sty with - | some html => return html - | none => return No non-structural morphisms found. +/-- The kind of the context. -/ +inductive Kind where + | monoidal : Kind + | bicategory : Kind + | none : Kind + +/-- The name of the context. -/ +def Kind.name : Kind → Name + | Kind.monoidal => `monoidal + | Kind.bicategory => `bicategory + | Kind.none => default +/-- Given an expression, return the kind of the context. -/ +def mkKind (e : Expr) : MetaM Kind := do + let e ← instantiateMVars e + let e ← (match (← whnfR e).eq? with + | some (_, lhs, _) => return lhs + | none => return e) + let ctx? ← BicategoryLike.mkContext? (ρ := Bicategory.Context) e + match ctx? with + | .some _ => return .bicategory + | .none => + let ctx? ← BicategoryLike.mkContext? (ρ := Monoidal.Context) e + match ctx? with + | .some _ => return .monoidal + | .none => return .none + +open scoped Jsx in /-- Given a 2-morphism, return a string diagram. Otherwise `none`. -/ def stringM? (e : Expr) : MetaM (Option Html) := do let e ← instantiateMVars e - let some ctx ← mkContext? e | return none - return some <| ← MonoidalM.run ctx <| fromExpr e + let k ← mkKind e + let x : Option (List (List Node) × List (List Strand)) ← (match k with + | .monoidal => do + let .some ctx ← BicategoryLike.mkContext? (ρ := Monoidal.Context) e | return .none + CoherenceM.run (ctx := ctx) do + let e' := (← BicategoryLike.eval k.name (← MkMor₂.ofExpr e)).expr + return .some (← e'.nodes, ← e'.strands) + | .bicategory => do + let .some ctx ← BicategoryLike.mkContext? (ρ := Bicategory.Context) e | return .none + CoherenceM.run (ctx := ctx) do + let e' := (← BicategoryLike.eval k.name (← MkMor₂.ofExpr e)).expr + return .some (← e'.nodes, ← e'.strands) + | .none => return .none) + match x with + | .none => return none + | .some (nodes, strands) => do + DiagramBuilderM.run do + mkStringDiagram nodes strands + trace[string_diagram] "Penrose substance: \n{(← get).sub}" + match ← DiagramBuilderM.buildDiagram dsl sty with + | some html => return html + | none => return No non-structural morphisms found. open scoped Jsx in /-- Help function for displaying two string diagrams in an equality. -/ diff --git a/scripts/noshake.json b/scripts/noshake.json index 8c9095fee0672..9360cd39d6f6e 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -374,10 +374,16 @@ ["Mathlib.Algebra.Order.Field.Basic"], "Mathlib.CategoryTheory.Sites.IsSheafFor": ["Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono"], + "Mathlib.CategoryTheory.Monoidal.Rigid.Basic": + ["Mathlib.Tactic.CategoryTheory.Monoidal.Basic"], + "Mathlib.CategoryTheory.Monoidal.Braided.Basic": + ["Mathlib.Tactic.CategoryTheory.Monoidal.Basic"], "Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits": ["Mathlib.CategoryTheory.Limits.Shapes.Pullback.HasPullback", "Mathlib.CategoryTheory.Limits.Shapes.Pullbacks"], "Mathlib.CategoryTheory.Limits.IsLimit": ["Batteries.Tactic.Congr"], + "Mathlib.CategoryTheory.Bicategory.Adjunction": + ["Mathlib.Tactic.CategoryTheory.Bicategory.Basic"], "Mathlib.CategoryTheory.Bicategory.Functor.Oplax": ["Mathlib.Tactic.CategoryTheory.ToApp"], "Mathlib.CategoryTheory.Bicategory.Functor.Lax": diff --git a/test/CategoryTheory/Bicategory/Basic.lean b/test/CategoryTheory/Bicategory/Basic.lean new file mode 100644 index 0000000000000..14c74e2ad760c --- /dev/null +++ b/test/CategoryTheory/Bicategory/Basic.lean @@ -0,0 +1,21 @@ +import Mathlib.Tactic.CategoryTheory.Bicategory.Basic + +open CategoryTheory Mathlib.Tactic BicategoryLike +open Bicategory + +universe w v u + +variable {B : Type u} [Bicategory.{w, v} B] +variable {a b c d : B} + +example {f j : a ⟶ d} {g : a ⟶ b} {h : b ⟶ c} {i : c ⟶ d} + (η : f ⟶ g ≫ (h ≫ i)) (θ : (g ≫ h) ≫ i ⟶ j) : + η ⊗≫ θ = η ≫ (α_ _ _ _).inv ≫ θ := by + bicategory + +example {f : a ⟶ b} {g : b ⟶ c} {h i : c ⟶ d} (η : h ⟶ i) : + (f ≫ g) ◁ η = (α_ _ _ _).hom ≫ f ◁ g ◁ η ≫ (α_ _ _ _).inv := by + bicategory + +example {f g h : a ⟶ b} {η : f ⟶ g} {θ : g ⟶ h} : η ≫ θ = η ≫ θ := by + bicategory diff --git a/test/CategoryTheory/Bicategory/Normalize.lean b/test/CategoryTheory/Bicategory/Normalize.lean new file mode 100644 index 0000000000000..7e6b171a32ec0 --- /dev/null +++ b/test/CategoryTheory/Bicategory/Normalize.lean @@ -0,0 +1,54 @@ +import Mathlib.Tactic.CategoryTheory.Bicategory.Normalize + +open CategoryTheory Mathlib.Tactic BicategoryLike +open Bicategory + +/-- `normalize% η` is the normalization of the 2-morphism `η`. +1. The normalized 2-morphism is of the form `α₀ ≫ η₀ ≫ α₁ ≫ η₁ ≫ ... αₘ ≫ ηₘ ≫ αₘ₊₁` where + each `αᵢ` is a structural 2-morphism (consisting of associators and unitors), +2. each `ηᵢ` is a non-structural 2-morphism of the form `f₁ ◁ ... ◁ fₘ ◁ θ`, and +3. `θ` is of the form `ι ▷ g₁ ▷ ... ▷ gₗ` +-/ +elab "normalize% " t:term:51 : term => do + let e ← Lean.Elab.Term.elabTerm t none + let ctx : Bicategory.Context ← BicategoryLike.mkContext e + CoherenceM.run (ctx := ctx) do + return (← BicategoryLike.eval `bicategory (← MkMor₂.ofExpr e)).expr.e.e + +universe w v u + +variable {B : Type u} [Bicategory.{w, v} B] +variable {a b c d e : B} + +variable {f : a ⟶ b} {g : b ⟶ c} in +#guard_expr normalize% f ◁ 𝟙 g = (whiskerLeftIso f (Iso.refl g)).hom +variable {f : a ⟶ b} {g : b ⟶ c} in +#guard_expr normalize% 𝟙 f ▷ g = (whiskerRightIso (Iso.refl f) g).hom +variable {f : a ⟶ b} {g h i : b ⟶ c} {η : g ⟶ h} {θ : h ⟶ i} in +#guard_expr normalize% f ◁ (η ≫ θ) = _ ≫ f ◁ η ≫ _ ≫ f ◁ θ ≫ _ +variable {f g h : a ⟶ b} {i : b ⟶ c} {η : f ⟶ g} {θ : g ⟶ h} in +#guard_expr normalize% (η ≫ θ) ▷ i = _ ≫ η ▷ i ≫ _ ≫ θ ▷ i ≫ _ +variable {η : 𝟙 a ⟶ 𝟙 a} in +#guard_expr normalize% 𝟙 a ◁ η = _ ≫ η ≫ _ +variable {f : a ⟶ b} {g : b ⟶ c} {h i : c ⟶ d} {η : h ⟶ i} in +#guard_expr normalize% (f ≫ g) ◁ η = _ ≫ f ◁ g ◁ η ≫ _ +variable {η : 𝟙 a ⟶ 𝟙 a} in +#guard_expr normalize% η ▷ 𝟙 a = _ ≫ η ≫ _ +variable {f g : a ⟶ b} {h : b ⟶ c} {i : c ⟶ d} {η : f ⟶ g} in +#guard_expr normalize% η ▷ (h ≫ i) = _ ≫ η ▷ h ▷ i ≫ _ +variable {f : a ⟶ b} {g h : b ⟶ c} {i : c ⟶ d} {η : g ⟶ h} in +#guard_expr normalize% (f ◁ η) ▷ i = _ ≫ f ◁ η ▷ i ≫ _ +variable {f : a ⟶ b} in +#guard_expr normalize% (λ_ f).hom = (λ_ f).hom +variable {f : a ⟶ b} in +#guard_expr normalize% (λ_ f).inv = ((λ_ f).symm).hom +variable {f : a ⟶ b} in +#guard_expr normalize% (ρ_ f).hom = (ρ_ f).hom +variable {f : a ⟶ b} in +#guard_expr normalize% (ρ_ f).inv = ((ρ_ f).symm).hom +variable {f : a ⟶ b} {g : b ⟶ c} {h : c ⟶ d} in +#guard_expr normalize% (α_ f g h).hom = (α_ _ _ _).hom +variable {f : a ⟶ b} {g : b ⟶ c} {h : c ⟶ d} in +#guard_expr normalize% (α_ f g h).inv = ((α_ f g h).symm).hom +variable {f : a ⟶ b} {g : b ⟶ c} in +#guard_expr normalize% 𝟙 (f ≫ g) = (Iso.refl (f ≫ g)).hom diff --git a/test/CategoryTheory/Monoidal.lean b/test/CategoryTheory/Monoidal.lean deleted file mode 100644 index ef581db2d213a..0000000000000 --- a/test/CategoryTheory/Monoidal.lean +++ /dev/null @@ -1,52 +0,0 @@ -import Mathlib.Tactic.CategoryTheory.Monoidal -import Mathlib.Tactic.CategoryTheory.Coherence - -open CategoryTheory -open scoped MonoidalCategory - -universe v u - -variable {C : Type u} [Category.{v} C] [MonoidalCategory C] -variable {X Y Z W : C} (f : X ⟶ Y) (g : Y ⟶ Z) - -#guard_expr normalize% X ◁ 𝟙 Y = X ◁ 𝟙 Y -#guard_expr normalize% 𝟙 X ▷ Y = 𝟙 X ▷ Y -#guard_expr normalize% X ◁ (f ≫ g) = _ ≫ X ◁ f ≫ _ ≫ X ◁ g ≫ _ -#guard_expr normalize% (f ≫ g) ▷ Y = _ ≫ f ▷ Y ≫ _ ≫ g ▷ Y ≫ _ -#guard_expr normalize% 𝟙_ C ◁ f = _ ≫ f ≫ _ -#guard_expr normalize% (X ⊗ Y) ◁ f = _ ≫ X ◁ Y ◁ f ≫ _ -#guard_expr normalize% f ▷ 𝟙_ C = _ ≫ f ≫ _ -#guard_expr normalize% f ▷ (X ⊗ Y) = _ ≫ f ▷ X ▷ Y ≫ _ -#guard_expr normalize% (X ◁ f) ▷ Y = _ ≫ X ◁ f ▷ Y ≫ _ -#guard_expr normalize% (λ_ X).hom = (λ_ X).hom -#guard_expr normalize% (λ_ X).inv = (λ_ X).inv -#guard_expr normalize% (ρ_ X).hom = (ρ_ X).hom -#guard_expr normalize% (ρ_ X).inv = (ρ_ X).inv -#guard_expr normalize% (α_ X Y Z).hom = (α_ _ _ _).hom -#guard_expr normalize% (α_ X Y Z).inv = (α_ _ _ _).inv -#guard_expr normalize% 𝟙 (X ⊗ Y) = 𝟙 (X ⊗ Y) -variable {V₁ V₂ V₃ : C} (R : ∀ V₁ V₂ : C, V₁ ⊗ V₂ ⟶ V₂ ⊗ V₁) in -#guard_expr normalize% R V₁ V₂ ▷ V₃ ⊗≫ V₂ ◁ R V₁ V₃ = _ ≫ R V₁ V₂ ▷ V₃ ≫ _ ≫ V₂ ◁ R V₁ V₃ ≫ _ - -example (f : U ⟶ V ⊗ (W ⊗ X)) (g : (V ⊗ W) ⊗ X ⟶ Y) : - f ⊗≫ g = f ≫ 𝟙 _ ≫ (α_ _ _ _).inv ≫ g := by - monoidal_nf - repeat' apply congrArg₂ (· ≫ ·) ?_ <| congrArg₂ (· ≫ ·) rfl ?_ - all_goals pure_coherence - -example : (X ⊗ Y) ◁ f = (α_ _ _ _).hom ≫ X ◁ Y ◁ f ≫ (α_ _ _ _).inv := by - monoidal_nf - repeat' apply congrArg₂ (· ≫ ·) ?_ <| congrArg₂ (· ≫ ·) rfl ?_ - all_goals pure_coherence - -example : f ≫ g = f ≫ g := by - monoidal_nf - repeat' apply congrArg₂ (· ≫ ·) ?_ <| congrArg₂ (· ≫ ·) rfl ?_ - all_goals pure_coherence - -example {V₁ V₂ V₃ : C} (R : ∀ V₁ V₂ : C, V₁ ⊗ V₂ ⟶ V₂ ⊗ V₁) : - R V₁ V₂ ▷ V₃ ⊗≫ V₂ ◁ R V₁ V₃ = - R V₁ V₂ ▷ V₃ ≫ (α_ _ _ _).hom ⊗≫ 𝟙 _ ≫ V₂ ◁ R V₁ V₃ := by - monoidal_nf - repeat' apply congrArg₂ (· ≫ ·) ?_ <| congrArg₂ (· ≫ ·) rfl ?_ - all_goals pure_coherence diff --git a/test/CategoryTheory/Monoidal/Basic.lean b/test/CategoryTheory/Monoidal/Basic.lean new file mode 100644 index 0000000000000..c003140e47a35 --- /dev/null +++ b/test/CategoryTheory/Monoidal/Basic.lean @@ -0,0 +1,27 @@ +import Mathlib.Tactic.CategoryTheory.Monoidal.Basic + +open CategoryTheory Mathlib.Tactic BicategoryLike +open MonoidalCategory + +universe v u + +variable {C : Type u} [Category.{v} C] [MonoidalCategory C] +variable {X Y Z W : C} (f : X ⟶ Y) (g : Y ⟶ Z) + +example (f : U ⟶ V ⊗ (W ⊗ X)) (g : (V ⊗ W) ⊗ X ⟶ Y) : + f ⊗≫ g = f ≫ (α_ _ _ _).inv ≫ g := by + monoidal + +example (f : Z ⟶ W) : (X ⊗ Y) ◁ f = (α_ _ _ _).hom ≫ X ◁ Y ◁ f ≫ (α_ _ _ _).inv := by + monoidal + +example : f ≫ g = f ≫ g := by + monoidal + +example : (f ⊗ g) ▷ X = (α_ _ _ _).hom ≫ (f ⊗ g ▷ X) ≫ (α_ _ _ _).inv := by + monoidal + +example {V₁ V₂ V₃ : C} (R : ∀ V₁ V₂ : C, V₁ ⊗ V₂ ⟶ V₂ ⊗ V₁) : + R V₁ V₂ ▷ V₃ ⊗≫ V₂ ◁ R V₁ V₃ = + R V₁ V₂ ▷ V₃ ≫ (α_ _ _ _).hom ⊗≫ 𝟙 _ ≫ V₂ ◁ R V₁ V₃ := by + monoidal diff --git a/test/CategoryTheory/Monoidal/Normalize.lean b/test/CategoryTheory/Monoidal/Normalize.lean new file mode 100644 index 0000000000000..9ae14f44ac833 --- /dev/null +++ b/test/CategoryTheory/Monoidal/Normalize.lean @@ -0,0 +1,41 @@ +import Mathlib.Tactic.CategoryTheory.Monoidal.Normalize + +open CategoryTheory Mathlib.Tactic BicategoryLike +open MonoidalCategory + +/-- `normalize% η` is the normalization of the 2-morphism `η`. +1. The normalized 2-morphism is of the form `α₀ ≫ η₀ ≫ α₁ ≫ η₁ ≫ ... αₘ ≫ ηₘ ≫ αₘ₊₁` where + each `αᵢ` is a structural 2-morphism (consisting of associators and unitors), +2. each `ηᵢ` is a non-structural 2-morphism of the form `f₁ ◁ ... ◁ fₘ ◁ θ`, and +3. `θ` is of the form `ι ▷ g₁ ▷ ... ▷ gₗ` +-/ +elab "normalize% " t:term:51 : term => do + let e ← Lean.Elab.Term.elabTerm t none + let ctx : Monoidal.Context ← BicategoryLike.mkContext e + CoherenceM.run (ctx := ctx) do + return (← BicategoryLike.eval `monoidal (← MkMor₂.ofExpr e)).expr.e.e + +universe v u + +variable {C : Type u} [Category.{v} C] [MonoidalCategory C] +variable {X Y Z W : C} (f : X ⟶ Y) (g : Y ⟶ Z) + +#guard_expr normalize% X ◁ 𝟙 Y = (whiskerLeftIso X (Iso.refl Y)).hom +#guard_expr normalize% 𝟙 X ▷ Y = (whiskerRightIso (Iso.refl X) Y).hom +#guard_expr normalize% X ◁ (f ≫ g) = _ ≫ X ◁ f ≫ _ ≫ X ◁ g ≫ _ +#guard_expr normalize% (f ≫ g) ▷ Y = _ ≫ f ▷ Y ≫ _ ≫ g ▷ Y ≫ _ +#guard_expr normalize% 𝟙_ C ◁ f = _ ≫ f ≫ _ +#guard_expr normalize% (X ⊗ Y) ◁ f = _ ≫ X ◁ Y ◁ f ≫ _ +#guard_expr normalize% f ▷ 𝟙_ C = _ ≫ f ≫ _ +#guard_expr normalize% f ▷ (X ⊗ Y) = _ ≫ f ▷ X ▷ Y ≫ _ +#guard_expr normalize% (X ◁ f) ▷ Y = _ ≫ X ◁ f ▷ Y ≫ _ +#guard_expr normalize% (λ_ X).hom = (λ_ X).hom +#guard_expr normalize% (λ_ X).inv = ((λ_ X).symm).hom +#guard_expr normalize% (ρ_ X).hom = (ρ_ X).hom +#guard_expr normalize% (ρ_ X).inv = ((ρ_ X).symm).hom +#guard_expr normalize% (α_ X Y Z).hom = (α_ _ _ _).hom +#guard_expr normalize% (α_ X Y Z).inv = ((α_ X Y Z).symm).hom +#guard_expr normalize% 𝟙 (X ⊗ Y) = (Iso.refl (X ⊗ Y)).hom +#guard_expr normalize% f ⊗ g = _ ≫ (f ⊗ g) ≫ _ +variable {V₁ V₂ V₃ : C} (R : ∀ V₁ V₂ : C, V₁ ⊗ V₂ ⟶ V₂ ⊗ V₁) in +#guard_expr normalize% R V₁ V₂ ▷ V₃ ⊗≫ V₂ ◁ R V₁ V₃ = _ ≫ R V₁ V₂ ▷ V₃ ≫ _ ≫ V₂ ◁ R V₁ V₃ ≫ _ diff --git a/test/StringDiagram.lean b/test/StringDiagram.lean index 4c3c3ffac0d93..f6c65dc77c848 100644 --- a/test/StringDiagram.lean +++ b/test/StringDiagram.lean @@ -3,10 +3,10 @@ import ProofWidgets.Component.Panel.SelectionPanel /-! ## Example use of string diagram widgets -/ -section MonoidalCategory - open ProofWidgets Mathlib.Tactic.Widget +section MonoidalCategory + open CategoryTheory open scoped MonoidalCategory @@ -279,6 +279,9 @@ info: [string_diagram] Penrose substance: info: [string_diagram] Penrose substance: Left(E_0_0_0, E_0_1_1) Left(E_0_1_1, E_0_2_2) + Left(E_1_0_0, E_1_2_2) + Left(E_2_0_0, E_2_1_1) + Left(E_3_0_0, E_3_2_2) Left(E_4_0_0, E_4_1_1) Left(E_4_1_1, E_4_2_2) Above(E_0_0_0, E_1_0_0) @@ -287,20 +290,23 @@ info: [string_diagram] Penrose substance: Above(E_3_0_0, E_4_0_0) Mor1 f_0_0 := MakeString (E_0_0_0, E_1_0_0) Mor1 f_0_2 := MakeString (E_0_1_1, E_1_0_0) - Mor1 f_0_4 := MakeString (E_0_2_2, E_1_0_0) + Mor1 f_0_4 := MakeString (E_0_2_2, E_1_2_2) Mor1 f_1_0 := MakeString (E_1_0_0, E_2_0_0) - Mor1 f_1_1 := MakeString (E_1_0_0, E_2_0_0) - Mor1 f_1_2 := MakeString (E_1_0_0, E_2_0_0) + Mor1 f_1_1 := MakeString (E_1_0_0, E_2_1_1) + Mor1 f_1_4 := MakeString (E_1_2_2, E_2_1_1) Mor1 f_2_0 := MakeString (E_2_0_0, E_3_0_0) - Mor1 f_2_1 := MakeString (E_2_0_0, E_3_0_0) - Mor1 f_2_2 := MakeString (E_2_0_0, E_3_0_0) + Mor1 f_2_2 := MakeString (E_2_1_1, E_3_0_0) + Mor1 f_2_3 := MakeString (E_2_1_1, E_3_2_2) Mor1 f_3_0 := MakeString (E_3_0_0, E_4_0_0) Mor1 f_3_1 := MakeString (E_3_0_0, E_4_1_1) - Mor1 f_3_2 := MakeString (E_3_0_0, E_4_2_2) + Mor1 f_3_4 := MakeString (E_3_2_2, E_4_2_2) [string_diagram] Penrose substance: Left(E_0_0_0, E_0_1_1) Left(E_0_1_1, E_0_2_2) + Left(E_1_0_0, E_1_1_1) + Left(E_2_0_0, E_2_2_2) + Left(E_3_0_0, E_3_1_1) Left(E_4_0_0, E_4_1_1) Left(E_4_1_1, E_4_2_2) Above(E_0_0_0, E_1_0_0) @@ -308,17 +314,17 @@ info: [string_diagram] Penrose substance: Above(E_2_0_0, E_3_0_0) Above(E_3_0_0, E_4_0_0) Mor1 f_0_0 := MakeString (E_0_0_0, E_1_0_0) - Mor1 f_0_2 := MakeString (E_0_1_1, E_1_0_0) - Mor1 f_0_4 := MakeString (E_0_2_2, E_1_0_0) + Mor1 f_0_2 := MakeString (E_0_1_1, E_1_1_1) + Mor1 f_0_4 := MakeString (E_0_2_2, E_1_1_1) Mor1 f_1_0 := MakeString (E_1_0_0, E_2_0_0) - Mor1 f_1_1 := MakeString (E_1_0_0, E_2_0_0) - Mor1 f_1_2 := MakeString (E_1_0_0, E_2_0_0) + Mor1 f_1_2 := MakeString (E_1_1_1, E_2_0_0) + Mor1 f_1_3 := MakeString (E_1_1_1, E_2_2_2) Mor1 f_2_0 := MakeString (E_2_0_0, E_3_0_0) - Mor1 f_2_1 := MakeString (E_2_0_0, E_3_0_0) - Mor1 f_2_2 := MakeString (E_2_0_0, E_3_0_0) + Mor1 f_2_1 := MakeString (E_2_0_0, E_3_1_1) + Mor1 f_2_4 := MakeString (E_2_2_2, E_3_1_1) Mor1 f_3_0 := MakeString (E_3_0_0, E_4_0_0) - Mor1 f_3_1 := MakeString (E_3_0_0, E_4_1_1) - Mor1 f_3_2 := MakeString (E_3_0_0, E_4_2_2) + Mor1 f_3_2 := MakeString (E_3_1_1, E_4_1_1) + Mor1 f_3_3 := MakeString (E_3_1_1, E_4_2_2) -/ #guard_msgs (whitespace := lax) in #string_diagram yang_baxter'' @@ -440,3 +446,45 @@ info: [string_diagram] Penrose substance: #string_diagram yangBaxterLhs end MonoidalCategory + +section Bicategory + +open CategoryTheory + +set_option trace.string_diagram true + +/-- +info: [string_diagram] Penrose substance: + Left(E_0_0_0, E_0_1_1) + Left(E_1_0_0, E_1_1_1) + Left(E_2_0_0, E_2_1_1) + Left(E_3_0_0, E_3_1_1) + Above(E_0_0_0, E_1_0_0) + Above(E_1_0_0, E_2_0_0) + Above(E_2_0_0, E_3_0_0) + Mor1 f_0_0 := MakeString (E_0_0_0, E_1_0_0) + Mor1 f_0_2 := MakeString (E_0_1_1, E_1_1_1) + Mor1 f_1_0 := MakeString (E_1_0_0, E_2_0_0) + Mor1 f_1_2 := MakeString (E_1_1_1, E_2_1_1) + Mor1 f_2_0 := MakeString (E_2_0_0, E_3_0_0) + Mor1 f_2_2 := MakeString (E_2_1_1, E_3_1_1) + +[string_diagram] Penrose substance: + Left(E_0_0_0, E_0_1_1) + Left(E_1_0_0, E_1_1_1) + Left(E_2_0_0, E_2_1_1) + Left(E_3_0_0, E_3_1_1) + Above(E_0_0_0, E_1_0_0) + Above(E_1_0_0, E_2_0_0) + Above(E_2_0_0, E_3_0_0) + Mor1 f_0_0 := MakeString (E_0_0_0, E_1_0_0) + Mor1 f_0_2 := MakeString (E_0_1_1, E_1_1_1) + Mor1 f_1_0 := MakeString (E_1_0_0, E_2_0_0) + Mor1 f_1_2 := MakeString (E_1_1_1, E_2_1_1) + Mor1 f_2_0 := MakeString (E_2_0_0, E_3_0_0) + Mor1 f_2_2 := MakeString (E_2_1_1, E_3_1_1) +-/ +#guard_msgs (whitespace := lax) in +#string_diagram Bicategory.whisker_exchange + +end Bicategory From 48d8b1d577f2740caaa44f336ec63987c41a23df Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 18 Sep 2024 05:13:51 +0000 Subject: [PATCH 007/170] CI: fix mk_all (#16896) This should fix the `mk_all` step in CI that leaves through PRs that do not import all files. --- .github/build.in.yml | 23 ++++++++++++++++++++--- .github/workflows/bors.yml | 23 ++++++++++++++++++++--- .github/workflows/build.yml | 23 ++++++++++++++++++++--- .github/workflows/build_fork.yml | 23 ++++++++++++++++++++--- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/.github/build.in.yml b/.github/build.in.yml index 023ae1426b9ef..0681d86ddadf3 100644 --- a/.github/build.in.yml +++ b/.github/build.in.yml @@ -132,13 +132,25 @@ jobs: lake exe cache get Mathlib.Init lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + id: mk_all + run: | + + if ! lake exe mk_all --check + then + echo "Not all lean files are in the import all files" + echo "mk_all=false" >> "${GITHUB_OUTPUT}" + else + echo "mk_all=true" >> "${GITHUB_OUTPUT}" + fi + - name: build mathlib id: build uses: liskin/gh-problem-matcher-wrap@v3 with: linters: gcc run: | - bash -o pipefail -c "lake exe mk_all || echo \"There are unaccounted for files, but I am not failing yet\!\"; env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" + bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" - name: upload cache # We only upload the cache if the build started (whether succeeding, failing, or cancelled) @@ -194,8 +206,13 @@ jobs: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - run: lake exe mk_all --check + - name: Check {Mathlib, Tactic, Counterexamples, Archive}.lean + run: | + if [ ${{ steps.mk_all.outputs.mk_all }} == "false" ] + then + echo "Please run 'lake exe mk_all' to regenerate the import all files" + exit 1 + fi - name: check for noisy stdout lines id: noisy diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index ecd90d0749bb2..02e70351023a5 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -145,13 +145,25 @@ jobs: lake exe cache get Mathlib.Init lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + id: mk_all + run: | + + if ! lake exe mk_all --check + then + echo "Not all lean files are in the import all files" + echo "mk_all=false" >> "${GITHUB_OUTPUT}" + else + echo "mk_all=true" >> "${GITHUB_OUTPUT}" + fi + - name: build mathlib id: build uses: liskin/gh-problem-matcher-wrap@v3 with: linters: gcc run: | - bash -o pipefail -c "lake exe mk_all || echo \"There are unaccounted for files, but I am not failing yet\!\"; env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" + bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" - name: upload cache # We only upload the cache if the build started (whether succeeding, failing, or cancelled) @@ -207,8 +219,13 @@ jobs: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - run: lake exe mk_all --check + - name: Check {Mathlib, Tactic, Counterexamples, Archive}.lean + run: | + if [ ${{ steps.mk_all.outputs.mk_all }} == "false" ] + then + echo "Please run 'lake exe mk_all' to regenerate the import all files" + exit 1 + fi - name: check for noisy stdout lines id: noisy diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc7ca496b1391..cd482c1de4509 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -152,13 +152,25 @@ jobs: lake exe cache get Mathlib.Init lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + id: mk_all + run: | + + if ! lake exe mk_all --check + then + echo "Not all lean files are in the import all files" + echo "mk_all=false" >> "${GITHUB_OUTPUT}" + else + echo "mk_all=true" >> "${GITHUB_OUTPUT}" + fi + - name: build mathlib id: build uses: liskin/gh-problem-matcher-wrap@v3 with: linters: gcc run: | - bash -o pipefail -c "lake exe mk_all || echo \"There are unaccounted for files, but I am not failing yet\!\"; env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" + bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" - name: upload cache # We only upload the cache if the build started (whether succeeding, failing, or cancelled) @@ -214,8 +226,13 @@ jobs: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - run: lake exe mk_all --check + - name: Check {Mathlib, Tactic, Counterexamples, Archive}.lean + run: | + if [ ${{ steps.mk_all.outputs.mk_all }} == "false" ] + then + echo "Please run 'lake exe mk_all' to regenerate the import all files" + exit 1 + fi - name: check for noisy stdout lines id: noisy diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index dc971651acfde..f08ba63897a50 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -149,13 +149,25 @@ jobs: lake exe cache get Mathlib.Init lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + id: mk_all + run: | + + if ! lake exe mk_all --check + then + echo "Not all lean files are in the import all files" + echo "mk_all=false" >> "${GITHUB_OUTPUT}" + else + echo "mk_all=true" >> "${GITHUB_OUTPUT}" + fi + - name: build mathlib id: build uses: liskin/gh-problem-matcher-wrap@v3 with: linters: gcc run: | - bash -o pipefail -c "lake exe mk_all || echo \"There are unaccounted for files, but I am not failing yet\!\"; env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" + bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" - name: upload cache # We only upload the cache if the build started (whether succeeding, failing, or cancelled) @@ -211,8 +223,13 @@ jobs: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - run: lake exe mk_all --check + - name: Check {Mathlib, Tactic, Counterexamples, Archive}.lean + run: | + if [ ${{ steps.mk_all.outputs.mk_all }} == "false" ] + then + echo "Please run 'lake exe mk_all' to regenerate the import all files" + exit 1 + fi - name: check for noisy stdout lines id: noisy From 5b61ee99b42db6405a2264def12e5bc77378c667 Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Wed, 18 Sep 2024 06:15:52 +0000 Subject: [PATCH 008/170] feat(GroupTheory/Archimedean): `LinearOrderedCommGroupWithZero.discrete_or_denselyOrdered` (#15846) Co-authored-by: Yakov Pechersky --- Mathlib/Algebra/Order/Archimedean/Basic.lean | 5 +++ Mathlib/GroupTheory/ArchimedeanDensely.lean | 35 +++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Order/Archimedean/Basic.lean b/Mathlib/Algebra/Order/Archimedean/Basic.lean index c0968b4ac7e37..8706c7c0c0d17 100644 --- a/Mathlib/Algebra/Order/Archimedean/Basic.lean +++ b/Mathlib/Algebra/Order/Archimedean/Basic.lean @@ -427,3 +427,8 @@ instance (priority := 100) FloorRing.archimedean (α) [LinearOrderedField α] [F Archimedean α := by rw [archimedean_iff_int_le] exact fun x => ⟨⌈x⌉, Int.le_ceil x⟩ + +@[to_additive] +instance Units.instMulArchimedean (α) [OrderedCommMonoid α] [MulArchimedean α] : + MulArchimedean αˣ := + ⟨fun x {_} h ↦ MulArchimedean.arch x.val h⟩ diff --git a/Mathlib/GroupTheory/ArchimedeanDensely.lean b/Mathlib/GroupTheory/ArchimedeanDensely.lean index c57766d25a7ca..dddf5efd91a55 100644 --- a/Mathlib/GroupTheory/ArchimedeanDensely.lean +++ b/Mathlib/GroupTheory/ArchimedeanDensely.lean @@ -21,7 +21,7 @@ They are placed here in a separate file (rather than incorporated as a continuat `GroupTheory.Archimedean`) because they rely on some imports from pointwise lemmas. -/ -open Set +open Multiplicative Set -- no earlier file imports the necessary requirements for the next two @@ -210,3 +210,36 @@ lemma LinearOrderedCommGroup.discrete_or_denselyOrdered : refine (LinearOrderedAddCommGroup.discrete_or_denselyOrdered (Additive G)).imp ?_ id rintro ⟨f, hf⟩ exact ⟨AddEquiv.toMultiplicative' f, hf⟩ + +/-- Any nontrivial (has other than 0 and 1) linearly ordered mul-archimedean group with zero is +either isomorphic (and order-isomorphic) to `ℤₘ₀`, or is densely ordered. -/ +lemma LinearOrderedCommGroupWithZero.discrete_or_denselyOrdered (G : Type*) + [LinearOrderedCommGroupWithZero G] [Nontrivial Gˣ] [MulArchimedean G] : + Nonempty (G ≃*o ℤₘ₀) ∨ DenselyOrdered G := by + classical + refine (LinearOrderedCommGroup.discrete_or_denselyOrdered Gˣ).imp ?_ ?_ + · intro ⟨f⟩ + refine ⟨OrderMonoidIso.trans + ⟨WithZero.withZeroUnitsEquiv.symm, ?_⟩ ⟨f.withZero, ?_⟩⟩ + · intro + simp only [WithZero.withZeroUnitsEquiv, MulEquiv.symm_mk, + MulEquiv.toEquiv_eq_coe, Equiv.toFun_as_coe, EquivLike.coe_coe, MulEquiv.coe_mk, + Equiv.coe_fn_symm_mk ] + split_ifs <;> + simp_all [← Units.val_le_val] + · intro a b + induction a <;> induction b <;> + simp [MulEquiv.withZero] + · intro H + refine ⟨fun x y h ↦ ?_⟩ + rcases (zero_le' (a := x)).eq_or_lt with rfl|hx + · lift y to Gˣ using h.ne'.isUnit + obtain ⟨z, hz⟩ := exists_ne (1 : Gˣ) + refine ⟨(y * |z|ₘ⁻¹ : Gˣ), ?_, ?_⟩ + · simp [zero_lt_iff] + · rw [Units.val_lt_val] + simp [hz] + · obtain ⟨z, hz, hz'⟩ := H.dense (Units.mk0 x hx.ne') (Units.mk0 y (hx.trans h).ne') + (by simp [← Units.val_lt_val, h]) + refine ⟨z, ?_, ?_⟩ <;> + simpa [← Units.val_lt_val] From c5befd42d5d9755b17c292f81a721e72612b54e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Wed, 18 Sep 2024 06:51:45 +0000 Subject: [PATCH 009/170] =?UTF-8?q?chore(SetTheory/Cardinal/Basic):=20`Car?= =?UTF-8?q?dinal.IsLimit`=20=E2=86=92=20`IsSuccLimit`=20(#16899)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/SetTheory/Cardinal/Basic.lean | 71 ++++++++++++++++++---- Mathlib/SetTheory/Cardinal/Cofinality.lean | 17 ++++-- Mathlib/SetTheory/Cardinal/Ordinal.lean | 10 +-- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index 729fd4ba6c61f..d2e7454569b96 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -710,29 +710,44 @@ theorem add_one_le_succ (c : Cardinal.{u}) : c + 1 ≤ succ c := by /-- A cardinal is a limit if it is not zero or a successor cardinal. Note that `ℵ₀` is a limit cardinal by this definition, but `0` isn't. - -TODO: deprecate this in favor of `Order.IsSuccLimit`. -/ +Deprecated. Use `Order.IsSuccLimit` instead. -/ +@[deprecated IsSuccLimit (since := "2024-09-17")] def IsLimit (c : Cardinal) : Prop := c ≠ 0 ∧ IsSuccPrelimit c -protected theorem IsLimit.ne_zero {c} (h : IsLimit c) : c ≠ 0 := - h.1 +theorem ne_zero_of_isSuccLimit {c} (h : IsSuccLimit c) : c ≠ 0 := + h.ne_bot + +theorem isSuccPrelimit_zero : IsSuccPrelimit (0 : Cardinal) := + isSuccPrelimit_bot + +protected theorem isSuccLimit_iff {c : Cardinal} : IsSuccLimit c ↔ c ≠ 0 ∧ IsSuccPrelimit c := + isSuccLimit_iff +section deprecated + +set_option linter.deprecated false + +@[deprecated IsSuccLimit.isSuccPrelimit (since := "2024-09-17")] protected theorem IsLimit.isSuccPrelimit {c} (h : IsLimit c) : IsSuccPrelimit c := h.2 +@[deprecated ne_zero_of_isSuccLimit (since := "2024-09-17")] +protected theorem IsLimit.ne_zero {c} (h : IsLimit c) : c ≠ 0 := + h.1 + @[deprecated IsLimit.isSuccPrelimit (since := "2024-09-05")] alias IsLimit.isSuccLimit := IsLimit.isSuccPrelimit +@[deprecated IsSuccLimit.succ_lt (since := "2024-09-17")] theorem IsLimit.succ_lt {x c} (h : IsLimit c) : x < c → succ x < c := h.isSuccPrelimit.succ_lt -theorem isSuccPrelimit_zero : IsSuccPrelimit (0 : Cardinal) := - isSuccPrelimit_bot - @[deprecated isSuccPrelimit_zero (since := "2024-09-05")] alias isSuccLimit_zero := isSuccPrelimit_zero +end deprecated + /-- The indexed sum of cardinals is the cardinality of the indexed disjoint union, i.e. sigma type. -/ def sum {ι} (f : ι → Cardinal) : Cardinal := @@ -882,9 +897,19 @@ lemma exists_eq_of_iSup_eq_of_not_isSuccPrelimit rw [iSup, csSup_of_not_bddAbove hf, csSup_empty] exact isSuccPrelimit_bot -@[deprecated exists_eq_of_iSup_eq_of_not_isSuccPrelimit (since := "2024-09-05")] -alias exists_eq_of_iSup_eq_of_not_isSuccLimit := exists_eq_of_iSup_eq_of_not_isSuccPrelimit +lemma exists_eq_of_iSup_eq_of_not_isSuccLimit + {ι : Type u} [hι : Nonempty ι] (f : ι → Cardinal.{v}) (hf : BddAbove (range f)) + {c : Cardinal.{v}} (hc : ¬ IsSuccLimit c) + (h : ⨆ i, f i = c) : ∃ i, f i = c := by + rw [Cardinal.isSuccLimit_iff] at hc + refine (not_and_or.mp hc).elim (fun e ↦ ⟨hι.some, ?_⟩) + (Cardinal.exists_eq_of_iSup_eq_of_not_isSuccPrelimit.{u, v} f c · h) + cases not_not.mp e + rw [← le_zero_iff] at h ⊢ + exact (le_ciSup hf _).trans h +set_option linter.deprecated false in +@[deprecated exists_eq_of_iSup_eq_of_not_isSuccLimit (since := "2024-09-17")] lemma exists_eq_of_iSup_eq_of_not_isLimit {ι : Type u} [hι : Nonempty ι] (f : ι → Cardinal.{v}) (hf : BddAbove (range f)) (ω : Cardinal.{v}) (hω : ¬ ω.IsLimit) @@ -1354,24 +1379,46 @@ theorem isSuccPrelimit_aleph0 : IsSuccPrelimit ℵ₀ := rw [← nat_succ] apply nat_lt_aleph0 -@[deprecated isSuccPrelimit_aleph0 (since := "2024-09-05")] -alias isSuccLimit_aleph0 := isSuccPrelimit_aleph0 +theorem isSuccLimit_aleph0 : IsSuccLimit ℵ₀ := by + rw [Cardinal.isSuccLimit_iff] + exact ⟨aleph0_ne_zero, isSuccPrelimit_aleph0⟩ + +lemma not_isSuccLimit_natCast : (n : ℕ) → ¬ IsSuccLimit (n : Cardinal.{u}) + | 0, e => e.1 isMin_bot + | Nat.succ n, e => Order.not_isSuccPrelimit_succ _ (nat_succ n ▸ e.2) + +theorem not_isSuccLimit_of_lt_aleph0 {c : Cardinal} (h : c < ℵ₀) : ¬ IsSuccLimit c := by + obtain ⟨n, rfl⟩ := lt_aleph0.1 h + exact not_isSuccLimit_natCast n + +theorem aleph0_le_of_isSuccLimit {c : Cardinal} (h : IsSuccLimit c) : ℵ₀ ≤ c := by + contrapose! h + exact not_isSuccLimit_of_lt_aleph0 h +section deprecated + +set_option linter.deprecated false + +@[deprecated isSuccLimit_aleph0 (since := "2024-09-17")] theorem isLimit_aleph0 : IsLimit ℵ₀ := ⟨aleph0_ne_zero, isSuccPrelimit_aleph0⟩ +@[deprecated not_isSuccLimit_natCast (since := "2024-09-17")] lemma not_isLimit_natCast : (n : ℕ) → ¬ IsLimit (n : Cardinal.{u}) | 0, e => e.1 rfl | Nat.succ n, e => Order.not_isSuccPrelimit_succ _ (nat_succ n ▸ e.2) +@[deprecated aleph0_le_of_isSuccLimit (since := "2024-09-17")] theorem IsLimit.aleph0_le {c : Cardinal} (h : IsLimit c) : ℵ₀ ≤ c := by by_contra! h' rcases lt_aleph0.1 h' with ⟨n, rfl⟩ exact not_isLimit_natCast n h +end deprecated + lemma exists_eq_natCast_of_iSup_eq {ι : Type u} [Nonempty ι] (f : ι → Cardinal.{v}) (hf : BddAbove (range f)) (n : ℕ) (h : ⨆ i, f i = n) : ∃ i, f i = n := - exists_eq_of_iSup_eq_of_not_isLimit.{u, v} f hf _ (not_isLimit_natCast n) h + exists_eq_of_iSup_eq_of_not_isSuccLimit.{u, v} f hf (not_isSuccLimit_natCast n) h @[simp] theorem range_natCast : range ((↑) : ℕ → Cardinal) = Iio ℵ₀ := diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index daedeef924bcd..035f8671aa50d 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -806,12 +806,19 @@ theorem isStrongLimit_aleph0 : IsStrongLimit ℵ₀ := rcases lt_aleph0.1 hx with ⟨n, rfl⟩ exact mod_cast nat_lt_aleph0 (2 ^ n)⟩ +protected theorem IsStrongLimit.isSuccLimit {c} (H : IsStrongLimit c) : IsSuccLimit c := by + rw [Cardinal.isSuccLimit_iff] + exact ⟨H.ne_zero, isSuccPrelimit_of_succ_lt fun x h => + (succ_le_of_lt <| cantor x).trans_lt (H.two_power_lt h)⟩ + protected theorem IsStrongLimit.isSuccPrelimit {c} (H : IsStrongLimit c) : IsSuccPrelimit c := - isSuccPrelimit_of_succ_lt fun x h => (succ_le_of_lt <| cantor x).trans_lt (H.two_power_lt h) + H.isSuccLimit.isSuccPrelimit -@[deprecated IsStrongLimit.isSuccPrelimit (since := "2024-09-05")] -alias IsStrongLimit.isSuccLimit := IsStrongLimit.isSuccPrelimit +theorem IsStrongLimit.aleph0_le {c} (H : IsStrongLimit c) : ℵ₀ ≤ c := + aleph0_le_of_isSuccLimit H.isSuccLimit +set_option linter.deprecated false in +@[deprecated IsStrongLimit.isSuccLimit (since := "2024-09-17")] theorem IsStrongLimit.isLimit {c} (H : IsStrongLimit c) : IsLimit c := ⟨H.ne_zero, H.isSuccPrelimit⟩ @@ -836,7 +843,7 @@ theorem mk_bounded_subset {α : Type*} (h : ∀ x < #α, (2^x) < #α) {r : α rintro ⟨s, hs⟩ exact (not_unbounded_iff s).2 hs (unbounded_of_isEmpty s) have h' : IsStrongLimit #α := ⟨ha, h⟩ - have ha := h'.isLimit.aleph0_le + have ha := h'.aleph0_le apply le_antisymm · have : { s : Set α | Bounded r s } = ⋃ i, 𝒫{ j | r j i } := setOf_exists _ rw [← coe_setOf, this] @@ -871,7 +878,7 @@ theorem mk_subset_mk_lt_cof {α : Type*} (h : ∀ x < #α, (2^x) < #α) : exact lt_cof_type hs · refine @mk_le_of_injective α _ (fun x => Subtype.mk {x} ?_) ?_ · rw [mk_singleton] - exact one_lt_aleph0.trans_le (aleph0_le_cof.2 (ord_isLimit h'.isLimit.aleph0_le)) + exact one_lt_aleph0.trans_le (aleph0_le_cof.2 (ord_isLimit h'.aleph0_le)) · intro a b hab simpa [singleton_eq_singleton_iff] using hab diff --git a/Mathlib/SetTheory/Cardinal/Ordinal.lean b/Mathlib/SetTheory/Cardinal/Ordinal.lean index 90d9aec5d0486..f605981cb3c6b 100644 --- a/Mathlib/SetTheory/Cardinal/Ordinal.lean +++ b/Mathlib/SetTheory/Cardinal/Ordinal.lean @@ -783,8 +783,8 @@ protected theorem ciSup_add (hf : BddAbove (range f)) (c : Cardinal.{v}) : refine le_antisymm ?_ (ciSup_le' this) have bdd : BddAbove (range (f · + c)) := ⟨_, forall_mem_range.mpr this⟩ obtain hs | hs := lt_or_le (⨆ i, f i) ℵ₀ - · obtain ⟨i, hi⟩ := exists_eq_of_iSup_eq_of_not_isLimit - f hf _ (fun h ↦ hs.not_le h.aleph0_le) rfl + · obtain ⟨i, hi⟩ := exists_eq_of_iSup_eq_of_not_isSuccLimit + f hf (not_isSuccLimit_of_lt_aleph0 hs) rfl exact hi ▸ le_ciSup bdd i rw [add_eq_max hs, max_le_iff] exact ⟨ciSup_mono bdd fun i ↦ self_le_add_right _ c, @@ -812,8 +812,8 @@ protected theorem ciSup_mul (c : Cardinal.{v}) : (⨆ i, f i) * c = ⨆ i, f i * refine le_antisymm ?_ (ciSup_le' this) have bdd : BddAbove (range (f · * c)) := ⟨_, forall_mem_range.mpr this⟩ obtain hs | hs := lt_or_le (⨆ i, f i) ℵ₀ - · obtain ⟨i, hi⟩ := exists_eq_of_iSup_eq_of_not_isLimit - f hf _ (fun h ↦ hs.not_le h.aleph0_le) rfl + · obtain ⟨i, hi⟩ := exists_eq_of_iSup_eq_of_not_isSuccLimit + f hf (not_isSuccLimit_of_lt_aleph0 hs) rfl exact hi ▸ le_ciSup bdd i rw [mul_eq_max_of_aleph0_le_left hs h0, max_le_iff] obtain ⟨i, hi⟩ := exists_lt_of_lt_ciSup' (one_lt_aleph0.trans_le hs) @@ -852,7 +852,7 @@ theorem add_nat_inj {α β : Cardinal} (n : ℕ) : α + n = β + n ↔ α = β : theorem add_one_inj {α β : Cardinal} : α + 1 = β + 1 ↔ α = β := add_right_inj_of_lt_aleph0 one_lt_aleph0 -theorem add_le_add_iff_of_lt_aleph0 {α β γ : Cardinal} (γ₀ : γ < Cardinal.aleph0) : +theorem add_le_add_iff_of_lt_aleph0 {α β γ : Cardinal} (γ₀ : γ < ℵ₀) : α + γ ≤ β + γ ↔ α ≤ β := by refine ⟨fun h => ?_, fun h => add_le_add_right h γ⟩ contrapose h From f518a558c9c4af109709edc61eca3eb34977b530 Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Wed, 18 Sep 2024 07:39:09 +0000 Subject: [PATCH 010/170] feat: lemmas on permutations, cycles, etc. (#9602) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR establishes various lemmas in the theory of permutation groups, pertaining to the supports, cycle decompositions, and the conjugation action of `ConjAct (Equiv.Perm α)` on `Equiv.Perm α` This lemmas stem out PR #9359 and are used there to compute the cardinalities of the conjugacy classes of permutations. Co-authored-by: leanprover-community-mathlib4-bot Co-authored-by: Antoine Chambert-Loir Co-authored-by: Riccardo Brasca --- Mathlib.lean | 1 + Mathlib/GroupTheory/Perm/Basic.lean | 10 ++ Mathlib/GroupTheory/Perm/ConjAct.lean | 64 +++++++++ Mathlib/GroupTheory/Perm/Cycle/Basic.lean | 151 +++++++++++++++++++- Mathlib/GroupTheory/Perm/Cycle/Factors.lean | 114 +++++++++++++++ Mathlib/GroupTheory/Perm/Support.lean | 37 +++++ 6 files changed, 371 insertions(+), 6 deletions(-) create mode 100644 Mathlib/GroupTheory/Perm/ConjAct.lean diff --git a/Mathlib.lean b/Mathlib.lean index e2b16910f49da..4e881d75102cd 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2830,6 +2830,7 @@ import Mathlib.GroupTheory.PGroup import Mathlib.GroupTheory.Perm.Basic import Mathlib.GroupTheory.Perm.Closure import Mathlib.GroupTheory.Perm.ClosureSwap +import Mathlib.GroupTheory.Perm.ConjAct import Mathlib.GroupTheory.Perm.Cycle.Basic import Mathlib.GroupTheory.Perm.Cycle.Concrete import Mathlib.GroupTheory.Perm.Cycle.Factors diff --git a/Mathlib/GroupTheory/Perm/Basic.lean b/Mathlib/GroupTheory/Perm/Basic.lean index 7392c6b050125..5dc3ff87f4586 100644 --- a/Mathlib/GroupTheory/Perm/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Basic.lean @@ -404,6 +404,16 @@ theorem subtypePerm_ofSubtype (f : Perm (Subtype p)) : subtypePerm (ofSubtype f) (mem_iff_ofSubtype_apply_mem f) = f := Equiv.ext fun x => Subtype.coe_injective (ofSubtype_apply_coe f x) +theorem ofSubtype_subtypePerm_of_mem {p : α → Prop} [DecidablePred p] + {g : Perm α} (hg : ∀ (x : α), p x ↔ p (g x)) + {a : α} (ha : p a) : (ofSubtype (g.subtypePerm hg)) a = g a := + ofSubtype_apply_of_mem (g.subtypePerm hg) ha + +theorem ofSubtype_subtypePerm_of_not_mem {p : α → Prop} [DecidablePred p] + {g : Perm α} (hg : ∀ (x : α), p x ↔ p (g x)) + {a : α} (ha : ¬ p a) : (ofSubtype (g.subtypePerm hg)) a = a := + ofSubtype_apply_of_not_mem (g.subtypePerm hg) ha + /-- Permutations on a subtype are equivalent to permutations on the original type that fix pointwise the rest. -/ @[simps] diff --git a/Mathlib/GroupTheory/Perm/ConjAct.lean b/Mathlib/GroupTheory/Perm/ConjAct.lean new file mode 100644 index 0000000000000..33786abcf6552 --- /dev/null +++ b/Mathlib/GroupTheory/Perm/ConjAct.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2024 Antoine Chambert-Loir. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir +-/ +import Mathlib.Algebra.Group.Pointwise.Finset.Basic +import Mathlib.GroupTheory.GroupAction.ConjAct +import Mathlib.GroupTheory.Perm.Cycle.Basic +import Mathlib.GroupTheory.Perm.Cycle.Factors +import Mathlib.GroupTheory.Perm.Support +/-! # Some lemmas pertaining to the action of `ConjAct (Perm α)` on `Perm α` + +We prove some lemmas related to the action of `ConjAct (Perm α)` on `Perm α`: + +Let `α` be a decidable fintype. + +* `conj_support_eq` relates the support of `k • g` with that of `g` + +* `cycleFactorsFinset_conj_eq`, `mem_cycleFactorsFinset_conj'` + and `cycleFactorsFinset_conj` relate the set of cycles of `g`, `g.cycleFactorsFinset`, + with that for `k • g` + +-/ + +namespace Equiv.Perm + +open scoped Pointwise + +variable {α : Type*} [DecidableEq α] [Fintype α] + +/-- `a : α` belongs to the support of `k • g` iff + `k⁻¹ * a` belongs to the support of `g` -/ +theorem mem_conj_support (k : ConjAct (Perm α)) (g : Perm α) (a : α) : + a ∈ (k • g).support ↔ ConjAct.ofConjAct k⁻¹ a ∈ g.support := by + simp only [mem_support, ConjAct.smul_def, not_iff_not, coe_mul, + Function.comp_apply, ConjAct.ofConjAct_inv] + apply Equiv.apply_eq_iff_eq_symm_apply + +theorem cycleFactorsFinset_conj (g k : Perm α) : + (ConjAct.toConjAct k • g).cycleFactorsFinset = + Finset.map (MulAut.conj k).toEquiv.toEmbedding g.cycleFactorsFinset := by + ext c + rw [ConjAct.smul_def, ConjAct.ofConjAct_toConjAct, Finset.mem_map_equiv, + ← mem_cycleFactorsFinset_conj g k] + simp only [MulEquiv.toEquiv_eq_coe, MulEquiv.coe_toEquiv_symm, MulAut.conj_symm_apply] + group + +/-- A permutation `c` is a cycle of `g` iff `k • c` is a cycle of `k • g` -/ +@[simp] +theorem mem_cycleFactorsFinset_conj' + (k : ConjAct (Perm α)) (g c : Perm α) : + k • c ∈ (k • g).cycleFactorsFinset ↔ c ∈ g.cycleFactorsFinset := by + simp only [ConjAct.smul_def] + apply mem_cycleFactorsFinset_conj g k + +theorem cycleFactorsFinset_conj_eq + (k : ConjAct (Perm α)) (g : Perm α) : + cycleFactorsFinset (k • g) = k • cycleFactorsFinset g := by + ext c + rw [← mem_cycleFactorsFinset_conj' k⁻¹ (k • g) c] + simp only [inv_smul_smul] + exact Finset.inv_smul_mem_iff + +end Equiv.Perm diff --git a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean index e57ccd1bc59bb..a13b28ec141ca 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean @@ -359,9 +359,10 @@ theorem isCycle_swap_mul_aux₁ {α : Type*} [DecidableEq α] : ∀ (n : ℕ) {b x : α} {f : Perm α} (_ : (swap x (f x) * f) b ≠ b) (_ : (f ^ n) (f x) = b), ∃ i : ℤ, ((swap x (f x) * f) ^ i) (f x) = b := by intro n - induction' n with n hn - · exact fun _ h => ⟨0, h⟩ - · intro b x f hb h + induction n with + | zero => exact fun _ h => ⟨0, h⟩ + | succ n hn => + intro b x f hb h exact if hfbx : f x = b then ⟨0, hfbx⟩ else have : f b ≠ b ∧ b ≠ x := ne_and_ne_of_swap_mul_apply_ne_self hb @@ -379,9 +380,10 @@ theorem isCycle_swap_mul_aux₂ {α : Type*} [DecidableEq α] : ∀ (n : ℤ) {b x : α} {f : Perm α} (_ : (swap x (f x) * f) b ≠ b) (_ : (f ^ n) (f x) = b), ∃ i : ℤ, ((swap x (f x) * f) ^ i) (f x) = b := by intro n - induction' n with n n - · exact isCycle_swap_mul_aux₁ n - · intro b x f hb h + induction n with + | ofNat n => exact isCycle_swap_mul_aux₁ n + | negSucc n => + intro b x f hb h exact if hfbx' : f x = b then ⟨0, hfbx'⟩ else have : f b ≠ b ∧ b ≠ x := ne_and_ne_of_swap_mul_apply_ne_self hb @@ -985,3 +987,140 @@ theorem sum_mul_sum_eq_sum_perm (hσ : σ.IsCycleOn s) (f g : ι → α) : sum_smul_sum_eq_sum_perm hσ f g end Finset + +namespace Equiv.Perm + +theorem subtypePerm_apply_pow_of_mem {g : Perm α} {s : Finset α} + (hs : ∀ x : α, x ∈ s ↔ g x ∈ s) {n : ℕ} {x : α} (hx : x ∈ s) : + ((g.subtypePerm hs ^ n) (⟨x, hx⟩ : s) : α) = (g ^ n) x := by + simp only [subtypePerm_pow, subtypePerm_apply] + +theorem subtypePerm_apply_zpow_of_mem {g : Perm α} {s : Finset α} + (hs : ∀ x : α, x ∈ s ↔ g x ∈ s) {i : ℤ} {x : α} (hx : x ∈ s) : + ((g.subtypePerm hs ^ i) (⟨x, hx⟩ : s) : α) = (g ^ i) x := by + simp only [subtypePerm_zpow, subtypePerm_apply] + +variable [Fintype α] [DecidableEq α] + +/-- Restrict a permutation to its support -/ +def subtypePermOfSupport (c : Perm α) : Perm c.support := + subtypePerm c fun _ : α => apply_mem_support.symm + +/-- Restrict a permutation to a Finset containing its support -/ +def subtypePerm_of_support_le (c : Perm α) {s : Finset α} + (hcs : c.support ⊆ s) : Equiv.Perm s := + subtypePerm c (isInvariant_of_support_le hcs) + +/-- Support of a cycle is nonempty -/ +theorem IsCycle.nonempty_support {g : Perm α} (hg : g.IsCycle) : + g.support.Nonempty := by + rw [Finset.nonempty_iff_ne_empty, ne_eq, support_eq_empty_iff] + exact IsCycle.ne_one hg + +/-- Centralizer of a cycle is a power of that cycle on the cycle -/ +theorem IsCycle.commute_iff' {g c : Perm α} (hc : c.IsCycle) : + Commute g c ↔ + ∃ hc' : ∀ x : α, x ∈ c.support ↔ g x ∈ c.support, + subtypePerm g hc' ∈ Subgroup.zpowers c.subtypePermOfSupport := by + constructor + · intro hgc + have hgc' := mem_support_iff_of_commute hgc + use hgc' + obtain ⟨a, ha⟩ := IsCycle.nonempty_support hc + obtain ⟨i, hi⟩ := hc.sameCycle (mem_support.mp ha) (mem_support.mp ((hgc' a).mp ha)) + use i + ext ⟨x, hx⟩ + simp only [subtypePermOfSupport, Subtype.coe_mk, subtypePerm_apply] + rw [subtypePerm_apply_zpow_of_mem] + obtain ⟨j, rfl⟩ := hc.sameCycle (mem_support.mp ha) (mem_support.mp hx) + simp only [← mul_apply, Commute.eq (Commute.zpow_right hgc j)] + rw [← zpow_add, add_comm i j, zpow_add] + simp only [mul_apply, EmbeddingLike.apply_eq_iff_eq] + exact hi + · rintro ⟨hc', ⟨i, hi⟩⟩ + ext x + simp only [coe_mul, Function.comp_apply] + by_cases hx : x ∈ c.support + · suffices hi' : ∀ x ∈ c.support, g x = (c ^ i) x by + rw [hi' x hx, hi' (c x) (apply_mem_support.mpr hx)] + simp only [← mul_apply, ← zpow_add_one, ← zpow_one_add, add_comm] + intro x hx + have hix := Perm.congr_fun hi ⟨x, hx⟩ + simp only [← Subtype.coe_inj, subtypePermOfSupport, Subtype.coe_mk, subtypePerm_apply, + subtypePerm_apply_zpow_of_mem] at hix + exact hix.symm + · rw [not_mem_support.mp hx, eq_comm, ← not_mem_support] + contrapose! hx + exact (hc' x).mpr hx + +/-- A permutation `g` commutes with a cycle `c` if and only if + `c.support` is invariant under `g`, and `g` acts on it as a power of `c`. -/ +theorem IsCycle.commute_iff {g c : Perm α} (hc : c.IsCycle) : + Commute g c ↔ + ∃ hc' : ∀ x : α, x ∈ c.support ↔ g x ∈ c.support, + ofSubtype (subtypePerm g hc') ∈ Subgroup.zpowers c := by + simp_rw [hc.commute_iff', Subgroup.mem_zpowers_iff] + refine exists_congr fun hc' => exists_congr fun k => ?_ + rw [subtypePermOfSupport, subtypePerm_zpow c k] + simp only [Perm.ext_iff, subtypePerm_apply, Subtype.mk.injEq, Subtype.forall] + apply forall_congr' + intro a + by_cases ha : a ∈ c.support + · rw [imp_iff_right ha, ofSubtype_subtypePerm_of_mem hc' ha] + · rw [iff_true_left (fun b ↦ (ha b).elim), ofSubtype_apply_of_not_mem, ← not_mem_support] + · exact Finset.not_mem_mono (support_zpow_le c k) ha + · exact ha + +theorem zpow_eq_ofSubtype_subtypePerm_iff + {g c : Equiv.Perm α} {s : Finset α} + (hg : ∀ x, x ∈ s ↔ g x ∈ s) (hc : c.support ⊆ s) (n : ℤ) : + c ^ n = ofSubtype (g.subtypePerm hg) ↔ + c.subtypePerm (isInvariant_of_support_le hc) ^ n = g.subtypePerm hg := by + constructor + · intro h + ext ⟨x, hx⟩ + simp only [Perm.congr_fun h x, subtypePerm_apply_zpow_of_mem, Subtype.coe_mk, subtypePerm_apply] + rw [ofSubtype_apply_of_mem] + · simp only [Subtype.coe_mk, subtypePerm_apply] + · exact hx + · intro h; ext x + rw [← h] + by_cases hx : x ∈ s + · rw [ofSubtype_apply_of_mem (subtypePerm c _ ^ n) hx, + subtypePerm_zpow, subtypePerm_apply] + · rw [ofSubtype_apply_of_not_mem (subtypePerm c _ ^ n) hx, + ← not_mem_support] + exact fun hx' ↦ hx (hc (support_zpow_le _ _ hx')) + +theorem cycle_zpow_mem_support_iff {g : Perm α} + (hg : g.IsCycle) {n : ℤ} {x : α} (hx : g x ≠ x) : + (g ^ n) x = x ↔ n % g.support.card = 0 := by + set q := n / g.support.card + set r := n % g.support.card + have div_euc : r + g.support.card * q = n ∧ 0 ≤ r ∧ r < g.support.card := by + rw [← Int.ediv_emod_unique _] + · exact ⟨rfl, rfl⟩ + simp only [Int.natCast_pos] + apply lt_of_lt_of_le _ (IsCycle.two_le_card_support hg); norm_num + simp only [← hg.orderOf] at div_euc + obtain ⟨m, hm⟩ := Int.eq_ofNat_of_zero_le div_euc.2.1 + simp only [hm, Nat.cast_nonneg, Nat.cast_lt, true_and] at div_euc + rw [← div_euc.1, zpow_add g] + simp only [hm, Nat.cast_eq_zero, zpow_natCast, coe_mul, comp_apply,zpow_mul, + pow_orderOf_eq_one, one_zpow, coe_one, id_eq] + have : (g ^ m) x = x ↔ g ^ m = 1 := by + constructor + · intro hgm + simp only [IsCycle.pow_eq_one_iff hg] + use x + · intro hgm + simp only [hgm, coe_one, id_eq] + rw [this] + by_cases hm0 : m = 0 + · simp only [hm0, pow_zero, Nat.cast_zero] + · simp only [Nat.cast_eq_zero, hm0, iff_false] + exact pow_ne_one_of_lt_orderOf hm0 div_euc.2 + +end Perm + +end Equiv diff --git a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean index d6af59c007b46..421192a904fdc 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean @@ -291,6 +291,19 @@ theorem SameCycle.exists_pow_eq [DecidableEq α] [Fintype α] (f : Perm α) (h : rw [not_mem_support] at hx rw [pow_apply_eq_self_of_apply_eq_self hx, zpow_apply_eq_self_of_apply_eq_self hx] +theorem zpow_eq_zpow_on_iff [DecidableEq α] [Fintype α] + (g : Perm α) {m n : ℤ} {x : α} (hx : g x ≠ x) : + (g ^ m) x = (g ^ n) x ↔ + m % (g.cycleOf x).support.card = n % (g.cycleOf x).support.card := by + rw [Int.emod_eq_emod_iff_emod_sub_eq_zero] + conv_lhs => rw [← Int.sub_add_cancel m n, Int.add_comm, zpow_add] + simp only [coe_mul, Function.comp_apply, EmbeddingLike.apply_eq_iff_eq] + rw [← Int.dvd_iff_emod_eq_zero] + rw [← cycleOf_zpow_apply_self g x, cycle_zpow_mem_support_iff] + · rw [← Int.dvd_iff_emod_eq_zero] + · exact isCycle_cycleOf g hx + · simp only [mem_support, cycleOf_apply_self]; exact hx + end CycleOf @@ -575,6 +588,73 @@ theorem cycle_is_cycleOf {f c : Equiv.Perm α} {a : α} (ha : a ∈ c.support) Equiv.Perm.not_mem_support.mp (Finset.disjoint_left.mp (Equiv.Perm.Disjoint.disjoint_support hfc) ha) + +theorem eq_cycleOf_of_mem_cycleFactorsFinset_iff + (g c : Perm α) (hc : c ∈ g.cycleFactorsFinset) (x : α) : + c = g.cycleOf x ↔ x ∈ c.support := by + refine ⟨?_, (cycle_is_cycleOf · hc)⟩ + rintro rfl + rw [mem_support, cycleOf_apply_self, ne_eq, ← cycleOf_eq_one_iff] + exact (mem_cycleFactorsFinset_iff.mp hc).left.ne_one + +/-- A permutation `c` is a cycle of `g` iff `k * c * k⁻¹` is a cycle of `k * g * k⁻¹` -/ +theorem mem_cycleFactorsFinset_conj (g k c : Perm α) : + k * c * k⁻¹ ∈ (k * g * k⁻¹).cycleFactorsFinset ↔ c ∈ g.cycleFactorsFinset := by + suffices imp_lemma : ∀ {g k c : Perm α}, + c ∈ g.cycleFactorsFinset → k * c * k⁻¹ ∈ (k * g * k⁻¹).cycleFactorsFinset by + refine ⟨fun h ↦ ?_, imp_lemma⟩ + have aux : ∀ h : Perm α, h = k⁻¹ * (k * h * k⁻¹) * k := fun _ ↦ by group + rw [aux g, aux c] + exact imp_lemma h + intro g k c + simp only [mem_cycleFactorsFinset_iff] + apply And.imp IsCycle.conj + intro hc a ha + simp only [coe_mul, Function.comp_apply, EmbeddingLike.apply_eq_iff_eq] + apply hc + rw [mem_support] at ha ⊢ + contrapose! ha + simp only [mul_smul, ← Perm.smul_def] at ha ⊢ + rw [ha] + simp only [Perm.smul_def, apply_inv_self] + +/-- If a permutation commutes with every cycle of `g`, then it commutes with `g` + +NB. The converse is false. Commuting with every cycle of `g` means that we belong +to the kernel of the action of `Equiv.Perm α` on `g.cycleFactorsFinset` -/ +theorem commute_of_mem_cycleFactorsFinset_commute (k g : Perm α) + (hk : ∀ c ∈ g.cycleFactorsFinset, Commute k c) : + Commute k g := by + rw [← cycleFactorsFinset_noncommProd g (cycleFactorsFinset_mem_commute g)] + apply Finset.noncommProd_commute + simpa only [id_eq] using hk + +/-- The cycles of a permutation commute with it -/ +theorem self_mem_cycle_factors_commute {g c : Perm α} + (hc : c ∈ g.cycleFactorsFinset) : Commute c g := by + apply commute_of_mem_cycleFactorsFinset_commute + intro c' hc' + by_cases hcc' : c = c' + · rw [hcc'] + · apply g.cycleFactorsFinset_mem_commute hc hc'; exact hcc' + +/-- If `c` and `d` are cycles of `g`, then `d` stabilizes the support of `c` -/ +theorem mem_support_cycle_of_cycle {g d c : Perm α} + (hc : c ∈ g.cycleFactorsFinset) (hd : d ∈ g.cycleFactorsFinset) : + ∀ x : α, x ∈ c.support ↔ d x ∈ c.support := by + intro x + simp only [mem_support, not_iff_not] + by_cases h : c = d + · rw [← h, EmbeddingLike.apply_eq_iff_eq] + · rw [← Perm.mul_apply, + Commute.eq (cycleFactorsFinset_mem_commute g hc hd h), + mul_apply, EmbeddingLike.apply_eq_iff_eq] + +/-- If a permutation is a cycle of `g`, then its support is invariant under `g`-/ +theorem mem_cycleFactorsFinset_support {g c : Perm α} (hc : c ∈ g.cycleFactorsFinset) (a : α) : + a ∈ c.support ↔ g a ∈ c.support := + mem_support_iff_of_commute (self_mem_cycle_factors_commute hc).symm a + end CycleFactorsFinset @[elab_as_elim] @@ -644,6 +724,40 @@ theorem cycleFactorsFinset_mul_inv_mem_eq_sdiff [DecidableEq α] [Fintype α] {f · exact fun H => not_mem_empty _ (hd.disjoint_cycleFactorsFinset.le_bot (mem_inter_of_mem H hf)) +theorem IsCycle.forall_commute_iff [DecidableEq α] [Fintype α] (g z : Perm α) : + (∀ c ∈ g.cycleFactorsFinset, Commute z c) ↔ + ∀ c ∈ g.cycleFactorsFinset, + ∃ (hc : ∀ x : α, x ∈ c.support ↔ z x ∈ c.support), + ofSubtype (subtypePerm z hc) ∈ Subgroup.zpowers c := by + apply forall_congr' + intro c + apply imp_congr_right + intro hc + exact IsCycle.commute_iff (mem_cycleFactorsFinset_iff.mp hc).1 + +/-- A permutation restricted to the support of a cycle factor is that cycle factor -/ +theorem subtypePerm_on_cycleFactorsFinset [DecidableEq α] [Fintype α] + {g c : Perm α} (hc : c ∈ g.cycleFactorsFinset) : + g.subtypePerm (mem_cycleFactorsFinset_support hc) = c.subtypePermOfSupport := by + ext ⟨x, hx⟩ + simp only [subtypePerm_apply, Subtype.coe_mk, subtypePermOfSupport] + exact ((mem_cycleFactorsFinset_iff.mp hc).2 x hx).symm + +theorem commute_iff_of_mem_cycleFactorsFinset [DecidableEq α] [Fintype α]{g k c : Equiv.Perm α} + (hc : c ∈ g.cycleFactorsFinset) : + Commute k c ↔ + ∃ hc' : ∀ x : α, x ∈ c.support ↔ k x ∈ c.support, + k.subtypePerm hc' ∈ Subgroup.zpowers + (g.subtypePerm (mem_cycleFactorsFinset_support hc)) := by + rw [IsCycle.commute_iff' (mem_cycleFactorsFinset_iff.mp hc).1] + apply exists_congr + intro hc' + simp only [Subgroup.mem_zpowers_iff] + apply exists_congr + intro n + rw [Equiv.Perm.subtypePerm_on_cycleFactorsFinset hc] + + end cycleFactors end Perm diff --git a/Mathlib/GroupTheory/Perm/Support.lean b/Mathlib/GroupTheory/Perm/Support.lean index fce28868366c4..f95ba42476e2a 100644 --- a/Mathlib/GroupTheory/Perm/Support.lean +++ b/Mathlib/GroupTheory/Perm/Support.lean @@ -296,6 +296,12 @@ theorem support_congr (h : f.support ⊆ g.support) (h' : ∀ x ∈ g.support, f · rw [not_mem_support.mp hx, ← not_mem_support] exact fun H => hx (h H) +/-- If g and c commute, then g stabilizes the support of c -/ +theorem mem_support_iff_of_commute {g c : Perm α} (hgc : Commute g c) (x : α) : + x ∈ c.support ↔ g x ∈ c.support := by + simp only [mem_support, not_iff_not, ← mul_apply] + rw [← hgc, mul_apply, Equiv.apply_eq_iff_eq] + theorem support_mul_le (f g : Perm α) : (f * g).support ≤ f.support ⊔ g.support := fun x => by simp only [sup_eq_union] rw [mem_union, mem_support, mem_support, mem_support, mul_apply, ← not_and_or, not_imp_not] @@ -326,6 +332,37 @@ theorem support_inv (σ : Perm α) : support σ⁻¹ = σ.support := by theorem apply_mem_support {x : α} : f x ∈ f.support ↔ x ∈ f.support := by rw [mem_support, mem_support, Ne, Ne, apply_eq_iff_eq] +/-- The support of a permutation is invariant -/ +theorem isInvariant_of_support_le {c : Perm α} {s : Finset α} (hcs : c.support ≤ s) (x : α) : + x ∈ s ↔ c x ∈ s := by + by_cases hx' : x ∈ c.support + · simp only [hcs hx', true_iff, hcs (apply_mem_support.mpr hx')] + · rw [not_mem_support.mp hx'] + +/-- A permutation c is the extension of a restriction of g to s + iff its support is contained in s and its restriction is that of g -/ +lemma ofSubtype_eq_iff {g c : Equiv.Perm α} {s : Finset α} + (hg : ∀ x, x ∈ s ↔ g x ∈ s) : + ofSubtype (g.subtypePerm hg) = c ↔ + c.support ≤ s ∧ + ∀ (hc' : ∀ x, x ∈ s ↔ c x ∈ s), c.subtypePerm hc' = g.subtypePerm hg := by + simp only [Equiv.ext_iff, subtypePerm_apply, Subtype.mk.injEq, Subtype.forall] + constructor + · intro h + constructor + · intro a ha + by_contra ha' + rw [mem_support, ← h a, ofSubtype_apply_of_not_mem (p := (· ∈ s)) _ ha'] at ha + exact ha rfl + · intro _ a ha + rw [← h a, ofSubtype_apply_of_mem (p := (· ∈ s)) _ ha, subtypePerm_apply] + · rintro ⟨hc, h⟩ a + specialize h (isInvariant_of_support_le hc) + by_cases ha : a ∈ s + · rw [h a ha, ofSubtype_apply_of_mem (p := (· ∈ s)) _ ha, subtypePerm_apply] + · rw [ofSubtype_apply_of_not_mem (p := (· ∈ s)) _ ha, eq_comm, ← not_mem_support] + exact Finset.not_mem_mono hc ha + -- @[simp] -- Porting note (#10618): simp can prove this theorem pow_apply_mem_support {n : ℕ} {x : α} : (f ^ n) x ∈ f.support ↔ x ∈ f.support := by simp only [mem_support, ne_eq, apply_pow_apply_eq_iff] From 1cf58af1097dccf56d8562b8942147e31636a583 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Wed, 18 Sep 2024 08:24:10 +0000 Subject: [PATCH 011/170] feat(Combinatorics/SimpleGraph): add `Fintype` instance for `Path` (#13810) --- .../Connectivity/WalkCounting.lean | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean index 6116fb07ca9ba..51818e2375813 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean @@ -107,12 +107,36 @@ theorem coe_finsetWalkLength_eq (n : ℕ) (u v : V) : variable {G} -theorem Walk.mem_finsetWalkLength_iff_length_eq {n : ℕ} {u v : V} (p : G.Walk u v) : +theorem mem_finsetWalkLength_iff {n : ℕ} {u v : V} {p : G.Walk u v} : p ∈ G.finsetWalkLength n u v ↔ p.length = n := Set.ext_iff.mp (G.coe_finsetWalkLength_eq n u v) p variable (G) +/-- The `Finset` of walks from `u` to `v` with length less than `n`. See `finsetWalkLength` for +context. In particular, we use this definition for `SimpleGraph.Path.instFintype`. --/ +def finsetWalkLengthLT (n : ℕ) (u v : V) : Finset (G.Walk u v) := + (Finset.range n).disjiUnion + (fun l ↦ G.finsetWalkLength l u v) + (fun l _ l' _ hne _ hsl hsl' p hp ↦ + have hl : p.length = l := mem_finsetWalkLength_iff.mp (hsl hp) + have hl' : p.length = l' := mem_finsetWalkLength_iff.mp (hsl' hp) + False.elim <| hne <| hl.symm.trans hl') + +open Finset in +theorem coe_finsetWalkLengthLT_eq (n : ℕ) (u v : V) : + (G.finsetWalkLengthLT n u v : Set (G.Walk u v)) = {p : G.Walk u v | p.length < n} := by + ext p + simp [finsetWalkLengthLT, mem_coe, mem_disjiUnion, mem_finsetWalkLength_iff] + +variable {G} + +theorem mem_finsetWalkLengthLT_iff {n : ℕ} {u v : V} {p : G.Walk u v} : + p ∈ G.finsetWalkLengthLT n u v ↔ p.length < n := + Set.ext_iff.mp (G.coe_finsetWalkLengthLT_eq n u v) p + +variable (G) + instance fintypeSetWalkLength (u v : V) (n : ℕ) : Fintype {p : G.Walk u v | p.length = n} := Fintype.ofFinset (G.finsetWalkLength n u v) fun p => by rw [← Finset.mem_coe, coe_finsetWalkLength_eq] @@ -132,10 +156,30 @@ theorem card_set_walk_length_eq (u v : V) (n : ℕ) : Fintype.card_ofFinset (G.finsetWalkLength n u v) fun p => by rw [← Finset.mem_coe, coe_finsetWalkLength_eq] +instance fintypeSetWalkLengthLT (u v : V) (n : ℕ) : Fintype {p : G.Walk u v | p.length < n} := + Fintype.ofFinset (G.finsetWalkLengthLT n u v) fun p ↦ by + rw [← Finset.mem_coe, coe_finsetWalkLengthLT_eq] + +instance fintypeSubtypeWalkLengthLT (u v : V) (n : ℕ) : Fintype {p : G.Walk u v // p.length < n} := + fintypeSetWalkLengthLT G u v n + instance fintypeSetPathLength (u v : V) (n : ℕ) : Fintype {p : G.Walk u v | p.IsPath ∧ p.length = n} := Fintype.ofFinset ((G.finsetWalkLength n u v).filter Walk.IsPath) <| by - simp [Walk.mem_finsetWalkLength_iff_length_eq, and_comm] + simp [mem_finsetWalkLength_iff, and_comm] + +instance fintypeSubtypePathLength (u v : V) (n : ℕ) : + Fintype {p : G.Walk u v // p.IsPath ∧ p.length = n} := + fintypeSetPathLength G u v n + +instance fintypeSetPathLengthLT (u v : V) (n : ℕ) : + Fintype {p : G.Walk u v | p.IsPath ∧ p.length < n} := + Fintype.ofFinset ((G.finsetWalkLengthLT n u v).filter Walk.IsPath) <| by + simp [mem_finsetWalkLengthLT_iff, and_comm] + +instance fintypeSubtypePathLengthLT (u v : V) (n : ℕ) : + Fintype {p : G.Walk u v // p.IsPath ∧ p.length < n} := + fintypeSetPathLengthLT G u v n end LocallyFinite @@ -149,7 +193,7 @@ theorem reachable_iff_exists_finsetWalkLength_nonempty (u v : V) : · intro r refine r.elim_path fun p => ?_ refine ⟨⟨_, p.isPath.length_lt⟩, p, ?_⟩ - simp [Walk.mem_finsetWalkLength_iff_length_eq] + simp [mem_finsetWalkLength_iff] · rintro ⟨_, p, _⟩ exact ⟨p⟩ @@ -166,6 +210,15 @@ instance : Decidable G.Connected := by rw [connected_iff, ← Finset.univ_nonempty_iff] infer_instance +open Finset in +instance Path.instFintype {u v : V} : Fintype (G.Path u v) where + elems := (univ (α := { p : G.Walk u v | p.IsPath ∧ p.length < Fintype.card V })).map + ⟨fun p ↦ { val := p.val, property := p.prop.left }, + fun _ _ h ↦ SetCoe.ext <| Subtype.mk.injEq .. ▸ h⟩ + complete p := mem_map.mpr ⟨ + ⟨p.val, ⟨p.prop, p.prop.length_lt⟩⟩, + ⟨mem_univ _, rfl⟩⟩ + instance instDecidableMemSupp (c : G.ConnectedComponent) (v : V) : Decidable (v ∈ c.supp) := c.recOn (fun w ↦ decidable_of_iff (G.Reachable v w) <| by simp) (fun _ _ _ _ ↦ Subsingleton.elim _ _) From 474d4295d95039facf17d5360a8ca1f107e49a63 Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Wed, 18 Sep 2024 08:24:12 +0000 Subject: [PATCH 012/170] chore: update Mathlib dependencies 2024-09-18 (#16909) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index 8f89ac7897311..21d9737992048 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "46fed98b5cac2b1ea64e363b420c382ed1af0d85", + "rev": "2ce0037d487217469a1efeb9ea8196fe15ab9c46", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 36a333acab7d3d491bc1aa43306cced21189ab3a Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Wed, 18 Sep 2024 09:20:57 +0000 Subject: [PATCH 013/170] feat(Analysis/Fourier/ZMod): DFT preserves even/odd functions (#16911) --- Mathlib/Algebra/Group/EvenFunction.lean | 23 ++++++++++++++++++++--- Mathlib/Analysis/Fourier/ZMod.lean | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Mathlib/Algebra/Group/EvenFunction.lean b/Mathlib/Algebra/Group/EvenFunction.lean index feb60ac3f85d1..3896969ce6795 100644 --- a/Mathlib/Algebra/Group/EvenFunction.lean +++ b/Mathlib/Algebra/Group/EvenFunction.lean @@ -5,6 +5,7 @@ Authors: David Loeffler -/ import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.Module.Defs +import Mathlib.Algebra.BigOperators.Group.Finset /-! # Even and odd functions @@ -17,6 +18,8 @@ conflicting with the root-level definitions `Even` and `Odd` (which, for functio function takes even resp. odd _values_, a wholly different concept). -/ +open scoped BigOperators + namespace Function variable {α β : Type*} [Neg α] @@ -122,14 +125,28 @@ lemma Odd.mul_odd [HasDistribNeg R] (hf : f.Odd) (hg : g.Odd) : (f * g).Even := end mul +section torsionfree + +-- need to redeclare variables since `InvolutiveNeg α` conflicts with `Neg α` +variable {α β : Type*} [AddCommGroup β] [NoZeroSMulDivisors ℕ β] {f : α → β} + /-- If `f` is both even and odd, and its target is a torsion-free commutative additive group, then `f = 0`. -/ -lemma zero_of_even_and_odd [AddCommGroup β] [NoZeroSMulDivisors ℕ β] - {f : α → β} (he : f.Even) (ho : f.Odd) : - f = 0 := by +lemma zero_of_even_and_odd [Neg α] (he : f.Even) (ho : f.Odd) : f = 0 := by ext r rw [Pi.zero_apply, ← neg_eq_self ℕ, ← ho, he] +/-- The sum of the values of an odd function is 0. -/ +lemma Odd.sum_eq_zero [Fintype α] [InvolutiveNeg α] {f : α → β} (hf : f.Odd) : ∑ a, f a = 0 := by + simpa only [neg_eq_self ℕ, Finset.sum_neg_distrib, funext hf, Equiv.neg_apply] using + Equiv.sum_comp (.neg α) f + +/-- An odd function vanishes at zero. -/ +lemma Odd.map_zero [NegZeroClass α] (hf : f.Odd) : f 0 = 0 := by + simp only [← neg_eq_self ℕ, ← hf 0, neg_zero] + +end torsionfree + end Function diff --git a/Mathlib/Analysis/Fourier/ZMod.lean b/Mathlib/Analysis/Fourier/ZMod.lean index e817057d937c2..4fad478f0bc2c 100644 --- a/Mathlib/Analysis/Fourier/ZMod.lean +++ b/Mathlib/Analysis/Fourier/ZMod.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 David Loeffler. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Loeffler -/ +import Mathlib.Algebra.Group.EvenFunction import Mathlib.Analysis.SpecialFunctions.Complex.CircleAddChar import Mathlib.Analysis.Fourier.FourierTransform import Mathlib.NumberTheory.DirichletCharacter.GaussSum @@ -177,6 +178,25 @@ lemma dft_comp_unitMul (Φ : ZMod N → E) (u : (ZMod N)ˣ) (k : ZMod N) : refine Fintype.sum_equiv u.mulLeft _ _ fun x ↦ ?_ simp only [mul_comm u.val, u.mulLeft_apply, ← mul_assoc, u.mul_inv_cancel_right] +section signs + +/-- The discrete Fourier transform of `Φ` is even if and only if `Φ` itself is. -/ +lemma dft_even_iff {Φ : ZMod N → ℂ} : (𝓕 Φ).Even ↔ Φ.Even := by + have h {f : ZMod N → ℂ} (hf : f.Even) : (𝓕 f).Even := by + simp only [Function.Even, ← congr_fun (dft_comp_neg f), funext hf, implies_true] + refine ⟨fun hΦ x ↦ ?_, h⟩ + simpa only [neg_neg, smul_right_inj (NeZero.ne (N : ℂ)), dft_dft] using h hΦ (-x) + +/-- The discrete Fourier transform of `Φ` is odd if and only if `Φ` itself is. -/ +lemma dft_odd_iff {Φ : ZMod N → ℂ} : (𝓕 Φ).Odd ↔ Φ.Odd := by + have h {f : ZMod N → ℂ} (hf : f.Odd) : (𝓕 f).Odd := by + simp only [Function.Odd, ← congr_fun (dft_comp_neg f), funext hf, ← Pi.neg_apply, map_neg, + implies_true] + refine ⟨fun hΦ x ↦ ?_, h⟩ + simpa only [neg_neg, dft_dft, ← smul_neg, smul_right_inj (NeZero.ne (N : ℂ))] using h hΦ (-x) + +end signs + end ZMod namespace DirichletCharacter From a98504654ef7be55256372c20fb12e889fc0d431 Mon Sep 17 00:00:00 2001 From: Scott Carnahan <128885296+ScottCarnahan@users.noreply.github.com> Date: Wed, 18 Sep 2024 09:37:36 +0000 Subject: [PATCH 014/170] feat (LinearAlgebra/RootSystem) : Construct root systems from bilinear forms on reflexive modules (#16722) This PR defines a function that takes a reflexive module `M` equipped with a bilinear form over a commutative ring, and produces a root pairing whose weight space is `M` and whose roots are the reflective vectors. This is a generalization of the standard construction of root systems from integral lattices. --- Mathlib.lean | 1 + Mathlib/LinearAlgebra/PerfectPairing.lean | 5 + .../LinearAlgebra/RootSystem/OfBilinear.lean | 182 ++++++++++++++++++ Mathlib/LinearAlgebra/SesquilinearForm.lean | 31 +++ 4 files changed, 219 insertions(+) create mode 100644 Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4e881d75102cd..afa21ce257b10 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3078,6 +3078,7 @@ import Mathlib.LinearAlgebra.Reflection import Mathlib.LinearAlgebra.RootSystem.Basic import Mathlib.LinearAlgebra.RootSystem.Defs import Mathlib.LinearAlgebra.RootSystem.Hom +import Mathlib.LinearAlgebra.RootSystem.OfBilinear import Mathlib.LinearAlgebra.RootSystem.RootPairingCat import Mathlib.LinearAlgebra.RootSystem.RootPositive import Mathlib.LinearAlgebra.SModEq diff --git a/Mathlib/LinearAlgebra/PerfectPairing.lean b/Mathlib/LinearAlgebra/PerfectPairing.lean index 8540645d0cf26..d5e2dd945411b 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing.lean @@ -140,6 +140,11 @@ def IsReflexive.toPerfectPairingDual : PerfectPairing R (Dual R M) M where bijectiveLeft := bijective_id bijectiveRight := bijective_dual_eval R M +@[simp] +lemma IsReflexive.toPerfectPairingDual_apply {f : Dual R M} {x : M} : + IsReflexive.toPerfectPairingDual (R := R) f x = f x := + rfl + variable (e : N ≃ₗ[R] Dual R M) namespace LinearEquiv diff --git a/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean b/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean new file mode 100644 index 0000000000000..026b7b23f30d7 --- /dev/null +++ b/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean @@ -0,0 +1,182 @@ +/- +Copyright (c) 2024 Scott Carnahan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Carnahan +-/ +import Mathlib.LinearAlgebra.RootSystem.Defs + +/-! +# Root pairings made from bilinear forms +A common construction of root systems is given by taking the set of all vectors in an integral +lattice for which reflection yields an automorphism of the lattice. In this file, we generalize +this construction, replacing the ring of integers with an arbitrary commutative ring and the +integral lattice with an arbitrary reflexive module equipped with a bilinear form. + +## Main definitions: + * `LinearMap.IsReflective`: Length is a regular value of `R`, and reflection is definable. + * `LinearMap.IsReflective.coroot`: The coroot corresponding to a reflective vector. + * `RootPairing.of_Bilinear`: The root pairing whose roots are reflective vectors. + +## TODO + * properties +-/ + +open Set Function Module + +noncomputable section + +variable {ι R M N : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + +namespace LinearMap + +/-- A vector `x` is reflective with respect to a bilinear form if multiplication by its norm is +injective, and for any vector `y`, the norm of `x` divides twice the inner product of `x` and `y`. +These conditions are what we need when describing reflection as a map taking `y` to +`y - 2 • (B x y) / (B x x) • x`. -/ +structure IsReflective (B : M →ₗ[R] M →ₗ[R] R) (x : M) : Prop := + regular : IsRegular (B x x) + dvd_two_mul : ∀ y, B x x ∣ 2 * B x y + +variable (B : M →ₗ[R] M →ₗ[R] R) {x : M} + +namespace IsReflective + +lemma of_dvd_two [IsDomain R] [NeZero (2 : R)] (hx : B x x ∣ 2) : + IsReflective B x where + regular := isRegular_of_ne_zero <| fun contra ↦ by simp [contra, two_ne_zero (α := R)] at hx + dvd_two_mul y := hx.mul_right (B x y) + +variable (hx : IsReflective B x) + +/-- The coroot attached to a reflective vector. -/ +def coroot : M →ₗ[R] R where + toFun y := (hx.2 y).choose + map_add' a b := by + refine hx.1.1 ?_ + simp only + rw [← (hx.2 (a + b)).choose_spec, mul_add, ← (hx.2 a).choose_spec, ← (hx.2 b).choose_spec, + map_add, mul_add] + map_smul' r a := by + refine hx.1.1 ?_ + simp only [RingHom.id_apply] + rw [← (hx.2 (r • a)).choose_spec, smul_eq_mul, mul_left_comm, ← (hx.2 a).choose_spec, map_smul, + two_mul, smul_eq_mul, two_mul, mul_add] + +@[simp] +lemma apply_self_mul_coroot_apply {y : M} : B x x * coroot B hx y = 2 * B x y := + (hx.dvd_two_mul y).choose_spec.symm + +@[simp] +lemma smul_coroot : B x x • coroot B hx = 2 • B x := by + ext y + simp [smul_apply, smul_eq_mul, nsmul_eq_mul, Nat.cast_ofNat, apply_self_mul_coroot_apply] + +@[simp] +lemma coroot_apply_self : coroot B hx x = 2 := + hx.regular.left <| by simp [mul_comm _ (B x x)] + +lemma isOrthogonal_reflection (hSB : LinearMap.IsSymm B) : + B.IsOrthogonal (Module.reflection (coroot_apply_self B hx)) := by + intro y z + simp only [LinearEquiv.coe_coe, reflection_apply, LinearMap.map_sub, map_smul, sub_apply, + smul_apply, smul_eq_mul] + refine hx.1.1 ?_ + simp only [mul_sub, ← mul_assoc, apply_self_mul_coroot_apply] + rw [sub_eq_iff_eq_add, ← hSB x y, RingHom.id_apply, mul_assoc _ _ (B x x), mul_comm _ (B x x), + apply_self_mul_coroot_apply] + ring + +lemma reflective_reflection (hSB : LinearMap.IsSymm B) {y : M} + (hx : IsReflective B x) (hy : IsReflective B y) : + IsReflective B (Module.reflection (coroot_apply_self B hx) y) := by + constructor + · rw [← LinearEquiv.coe_coe, isOrthogonal_reflection B hx hSB] + exact hy.1 + · intro z + have hz : Module.reflection (coroot_apply_self B hx) + (Module.reflection (coroot_apply_self B hx) z) = z := by + exact (LinearEquiv.eq_symm_apply (Module.reflection (coroot_apply_self B hx))).mp rfl + rw [← hz, ← LinearEquiv.coe_coe, isOrthogonal_reflection B hx hSB, + isOrthogonal_reflection B hx hSB] + exact hy.2 _ + +end IsReflective + +end LinearMap + +namespace RootPairing + +open LinearMap IsReflective + +/-- The root pairing given by all reflective vectors for a bilinear form. -/ +def ofBilinear [IsReflexive R M] (B : M →ₗ[R] M →ₗ[R] R) (hNB : LinearMap.Nondegenerate B) + (hSB : LinearMap.IsSymm B) (h2 : IsRegular (2 : R)) : + RootPairing {x : M | IsReflective B x} R M (Dual R M) where + toPerfectPairing := (IsReflexive.toPerfectPairingDual (R := R) (M := M)).flip + root := Embedding.subtype fun x ↦ IsReflective B x + coroot := + { toFun := fun x => IsReflective.coroot B x.2 + inj' := by + intro x y hxy + simp only [mem_setOf_eq] at hxy -- x* = y* + have h1 : ∀ z, IsReflective.coroot B x.2 z = IsReflective.coroot B y.2 z := + fun z => congrFun (congrArg DFunLike.coe hxy) z + have h2x : ∀ z, B x x * IsReflective.coroot B x.2 z = + B x x * IsReflective.coroot B y.2 z := + fun z => congrArg (HMul.hMul ((B x) x)) (h1 z) + have h2y : ∀ z, B y y * IsReflective.coroot B x.2 z = + B y y * IsReflective.coroot B y.2 z := + fun z => congrArg (HMul.hMul ((B y) y)) (h1 z) + simp_rw [apply_self_mul_coroot_apply B x.2] at h2x -- 2(x,z) = (x,x)y*(z) + simp_rw [apply_self_mul_coroot_apply B y.2] at h2y -- (y,y)x*(z) = 2(y,z) + have h2xy : B x x = B y y := by + refine h2.1 ?_ + dsimp only + specialize h2x y + rw [coroot_apply_self] at h2x + specialize h2y x + rw [coroot_apply_self] at h2y + rw [mul_comm, ← h2x, ← hSB, RingHom.id_apply, ← h2y, mul_comm] + rw [Subtype.ext_iff_val, ← sub_eq_zero] + refine hNB.1 _ (fun z => ?_) + rw [map_sub, LinearMap.sub_apply, sub_eq_zero] + refine h2.1 ?_ + dsimp only + rw [h2x z, ← h2y z, hxy, h2xy] } + root_coroot_two x := by + dsimp only [coe_setOf, Embedding.coe_subtype, PerfectPairing.toLin_apply, mem_setOf_eq, id_eq, + eq_mp_eq_cast, RingHom.id_apply, eq_mpr_eq_cast, cast_eq, LinearMap.sub_apply, + Embedding.coeFn_mk, PerfectPairing.flip_apply_apply] + exact coroot_apply_self B x.2 + reflection_perm x := + { toFun := fun y => ⟨(Module.reflection (coroot_apply_self B x.2) y), + reflective_reflection B hSB x.2 y.2⟩ + invFun := fun y => ⟨(Module.reflection (coroot_apply_self B x.2) y), + reflective_reflection B hSB x.2 y.2⟩ + left_inv := by + intro y + simp [involutive_reflection (coroot_apply_self B x.2) y] + right_inv := by + intro y + simp [involutive_reflection (coroot_apply_self B x.2) y] } + reflection_perm_root x y := by + simp [Module.reflection_apply] + reflection_perm_coroot x y := by + simp only [coe_setOf, mem_setOf_eq, Embedding.coeFn_mk, Embedding.coe_subtype, + PerfectPairing.flip_apply_apply, IsReflexive.toPerfectPairingDual_apply, Equiv.coe_fn_mk] + ext z + simp only [LinearMap.sub_apply, LinearMap.smul_apply, smul_eq_mul] + refine y.2.1.1 ?_ + simp only [mem_setOf_eq, PerfectPairing.flip_apply_apply, mul_sub, + apply_self_mul_coroot_apply B y.2, ← mul_assoc] + rw [← isOrthogonal_reflection B x.2 hSB y y, apply_self_mul_coroot_apply, ← hSB z, ← hSB z, + RingHom.id_apply, RingHom.id_apply, LinearEquiv.coe_coe, Module.reflection_apply, map_sub, + mul_sub, sub_eq_sub_iff_comm, sub_left_inj] + refine x.2.1.1 ?_ + simp only [mem_setOf_eq, map_smul, smul_eq_mul] + rw [← mul_assoc _ _ (B z x), ← mul_assoc _ _ (B z x), mul_left_comm, + apply_self_mul_coroot_apply B x.2, mul_left_comm (B x x), apply_self_mul_coroot_apply B x.2, + ← hSB x y, RingHom.id_apply, ← hSB x z, RingHom.id_apply] + ring + +end RootPairing diff --git a/Mathlib/LinearAlgebra/SesquilinearForm.lean b/Mathlib/LinearAlgebra/SesquilinearForm.lean index e1ee9539064ba..99617d933657d 100644 --- a/Mathlib/LinearAlgebra/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/SesquilinearForm.lean @@ -458,6 +458,37 @@ theorem IsAdjointPair.smul (c : R) (h : IsAdjointPair B B' f g) : end AddCommGroup +section OrthogonalMap + +variable {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] + (B : LinearMap.BilinForm R M) (f : Module.End R M) + +/-- A linear transformation `f` is orthogonal with respect to a bilinear form `B` if `B` is +bi-invariant with respect to `f`. -/ +def IsOrthogonal : Prop := + ∀ x y, B (f x) (f y) = B x y + +variable {B f} + +@[simp] +lemma _root_.LinearEquiv.isAdjointPair_symm_iff {f : M ≃ₗ[R] M} : + LinearMap.IsAdjointPair B B f f.symm ↔ B.IsOrthogonal f := + ⟨fun hf x y ↦ by simpa using hf x (f y), fun hf x y ↦ by simpa using hf x (f.symm y)⟩ + +lemma isOrthogonal_of_forall_apply_same + (h : IsLeftRegular (2 : R)) (hB : B.IsSymm) (hf : ∀ x, B (f x) (f x) = B x x) : + B.IsOrthogonal f := by + intro x y + suffices 2 * B (f x) (f y) = 2 * B x y from h this + have := hf (x + y) + simp only [map_add, add_apply, hf x, hf y, show B y x = B x y from hB.eq y x] at this + rw [show B (f y) (f x) = B (f x) (f y) from hB.eq (f y) (f x)] at this + simp only [add_assoc, add_right_inj] at this + simp only [← add_assoc, add_left_inj] at this + simpa only [← two_mul] using this + +end OrthogonalMap + end AdjointPair /-! ### Self-adjoint pairs -/ From e9dae23262f10bb4d74741f16c94081f57f96d10 Mon Sep 17 00:00:00 2001 From: Etienne Date: Wed, 18 Sep 2024 10:16:00 +0000 Subject: [PATCH 015/170] feat: rewrite cylinders and projective families of measures in terms of `Finset.restrict` (#16327) Rewrite cylinders and projective families of measures in terms of `Finset.restrict`. This avoids type ascription, and allows to rewrite a restriction as the composition of two restrictions, which is helpful when manipulating projective families. Co-authored-by: Etienne <66847262+EtienneC30@users.noreply.github.com> --- Mathlib/Data/Finset/Pi.lean | 5 +++ Mathlib/Data/Set/Function.lean | 5 +++ .../Constructions/Cylinders.lean | 34 +++++++++---------- .../Constructions/Projective.lean | 13 ++++--- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Mathlib/Data/Finset/Pi.lean b/Mathlib/Data/Finset/Pi.lean index ae0a476ddb399..658eb02ed3164 100644 --- a/Mathlib/Data/Finset/Pi.lean +++ b/Mathlib/Data/Finset/Pi.lean @@ -154,12 +154,17 @@ variable {π : ι → Type*} @[simp] def restrict (s : Finset ι) (f : (i : ι) → π i) : (i : s) → π i := fun x ↦ f x +theorem restrict_def (s : Finset ι) : s.restrict (π := π) = fun f x ↦ f x := rfl + /-- If a function `f` is restricted to a finite set `t`, and `s ⊆ t`, this is the restriction to `s`. -/ @[simp] def restrict₂ {s t : Finset ι} (hst : s ⊆ t) (f : (i : t) → π i) : (i : s) → π i := fun x ↦ f ⟨x.1, hst x.2⟩ +theorem restrict₂_def {s t : Finset ι} (hst : s ⊆ t) : + restrict₂ (π := π) hst = fun f x ↦ f ⟨x.1, hst x.2⟩ := rfl + theorem restrict₂_comp_restrict {s t : Finset ι} (hst : s ⊆ t) : (restrict₂ (π := π) hst) ∘ t.restrict = s.restrict := rfl diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index 0f86577bddfdf..99367bed783cb 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -44,6 +44,8 @@ section restrict takes an argument `↥s` instead of `Subtype s`. -/ def restrict (s : Set α) (f : ∀ a : α, π a) : ∀ a : s, π a := fun x => f x +theorem restrict_def (s : Set α) : s.restrict (π := π) = fun f x ↦ f x := rfl + theorem restrict_eq (f : α → β) (s : Set α) : s.restrict f = f ∘ Subtype.val := rfl @@ -115,6 +117,9 @@ theorem restrict_extend_compl_range (f : α → β) (g : α → γ) (g' : β → def restrict₂ {s t : Set α} (hst : s ⊆ t) (f : ∀ a : t, π a) : ∀ a : s, π a := fun x => f ⟨x.1, hst x.2⟩ +theorem restrict₂_def {s t : Set α} (hst : s ⊆ t) : + restrict₂ (π := π) hst = fun f x ↦ f ⟨x.1, hst x.2⟩ := rfl + theorem restrict₂_comp_restrict {s t : Set α} (hst : s ⊆ t) : (restrict₂ (π := π) hst) ∘ t.restrict = s.restrict := rfl diff --git a/Mathlib/MeasureTheory/Constructions/Cylinders.lean b/Mathlib/MeasureTheory/Constructions/Cylinders.lean index dcdfe7b8f1a19..381a125b81a96 100644 --- a/Mathlib/MeasureTheory/Constructions/Cylinders.lean +++ b/Mathlib/MeasureTheory/Constructions/Cylinders.lean @@ -150,11 +150,11 @@ section cylinder /-- Given a finite set `s` of indices, a cylinder is the preimage of a set `S` of `∀ i : s, α i` by the projection from `∀ i, α i` to `∀ i : s, α i`. -/ def cylinder (s : Finset ι) (S : Set (∀ i : s, α i)) : Set (∀ i, α i) := - (fun (f : ∀ i, α i) (i : s) ↦ f i) ⁻¹' S + s.restrict ⁻¹' S @[simp] theorem mem_cylinder (s : Finset ι) (S : Set (∀ i : s, α i)) (f : ∀ i, α i) : - f ∈ cylinder s S ↔ (fun i : s ↦ f i) ∈ S := + f ∈ cylinder s S ↔ s.restrict f ∈ S := mem_preimage @[simp] @@ -178,7 +178,7 @@ theorem cylinder_eq_empty_iff [h_nonempty : Nonempty (∀ i, α i)] (s : Finset let f' : ∀ i, α i := fun i ↦ if hi : i ∈ s then f ⟨i, hi⟩ else h_nonempty.some i have hf' : f' ∈ cylinder s S := by rw [mem_cylinder] - simpa only [f', Finset.coe_mem, dif_pos] + simpa only [Finset.restrict_def, Finset.coe_mem, dif_pos, f'] rw [h] at hf' exact not_mem_empty _ hf' @@ -186,8 +186,8 @@ theorem inter_cylinder (s₁ s₂ : Finset ι) (S₁ : Set (∀ i : s₁, α i)) [DecidableEq ι] : cylinder s₁ S₁ ∩ cylinder s₂ S₂ = cylinder (s₁ ∪ s₂) - ((fun f ↦ fun j : s₁ ↦ f ⟨j, Finset.mem_union_left s₂ j.prop⟩) ⁻¹' S₁ ∩ - (fun f ↦ fun j : s₂ ↦ f ⟨j, Finset.mem_union_right s₁ j.prop⟩) ⁻¹' S₂) := by + (Finset.restrict₂ Finset.subset_union_left ⁻¹' S₁ ∩ + Finset.restrict₂ Finset.subset_union_right ⁻¹' S₂) := by ext1 f; simp only [mem_inter_iff, mem_cylinder, mem_setOf_eq]; rfl theorem inter_cylinder_same (s : Finset ι) (S₁ : Set (∀ i : s, α i)) (S₂ : Set (∀ i : s, α i)) : @@ -198,8 +198,8 @@ theorem union_cylinder (s₁ s₂ : Finset ι) (S₁ : Set (∀ i : s₁, α i)) [DecidableEq ι] : cylinder s₁ S₁ ∪ cylinder s₂ S₂ = cylinder (s₁ ∪ s₂) - ((fun f ↦ fun j : s₁ ↦ f ⟨j, Finset.mem_union_left s₂ j.prop⟩) ⁻¹' S₁ ∪ - (fun f ↦ fun j : s₂ ↦ f ⟨j, Finset.mem_union_right s₁ j.prop⟩) ⁻¹' S₂) := by + (Finset.restrict₂ Finset.subset_union_left ⁻¹' S₁ ∪ + Finset.restrict₂ Finset.subset_union_right ⁻¹' S₂) := by ext1 f; simp only [mem_union, mem_cylinder, mem_setOf_eq]; rfl theorem union_cylinder_same (s : Finset ι) (S₁ : Set (∀ i : s, α i)) (S₂ : Set (∀ i : s, α i)) : @@ -217,7 +217,7 @@ theorem diff_cylinder_same (s : Finset ι) (S T : Set (∀ i : s, α i)) : theorem eq_of_cylinder_eq_of_subset [h_nonempty : Nonempty (∀ i, α i)] {I J : Finset ι} {S : Set (∀ i : I, α i)} {T : Set (∀ i : J, α i)} (h_eq : cylinder I S = cylinder J T) (hJI : J ⊆ I) : - S = (fun f : ∀ i : I, α i ↦ fun j : J ↦ f ⟨j, hJI j.prop⟩) ⁻¹' T := by + S = Finset.restrict₂ hJI ⁻¹' T := by rw [Set.ext_iff] at h_eq simp only [mem_cylinder] at h_eq ext1 f @@ -225,22 +225,20 @@ theorem eq_of_cylinder_eq_of_subset [h_nonempty : Nonempty (∀ i, α i)] {I J : classical specialize h_eq fun i ↦ if hi : i ∈ I then f ⟨i, hi⟩ else h_nonempty.some i have h_mem : ∀ j : J, ↑j ∈ I := fun j ↦ hJI j.prop - simp only [Finset.coe_mem, dite_true, h_mem] at h_eq - exact h_eq + simpa only [Finset.restrict_def, Finset.coe_mem, dite_true, h_mem] using h_eq theorem cylinder_eq_cylinder_union [DecidableEq ι] (I : Finset ι) (S : Set (∀ i : I, α i)) (J : Finset ι) : cylinder I S = - cylinder (I ∪ J) ((fun f ↦ fun j : I ↦ f ⟨j, Finset.mem_union_left J j.prop⟩) ⁻¹' S) := by - ext1 f; simp only [mem_cylinder, mem_preimage] + cylinder (I ∪ J) (Finset.restrict₂ Finset.subset_union_left ⁻¹' S) := by + ext1 f; simp only [mem_cylinder, Finset.restrict_def, Finset.restrict₂_def, mem_preimage] theorem disjoint_cylinder_iff [Nonempty (∀ i, α i)] {s t : Finset ι} {S : Set (∀ i : s, α i)} {T : Set (∀ i : t, α i)} [DecidableEq ι] : Disjoint (cylinder s S) (cylinder t T) ↔ Disjoint - ((fun f : ∀ i : (s ∪ t : Finset ι), α i - ↦ fun j : s ↦ f ⟨j, Finset.mem_union_left t j.prop⟩) ⁻¹' S) - ((fun f ↦ fun j : t ↦ f ⟨j, Finset.mem_union_right s j.prop⟩) ⁻¹' T) := by + (Finset.restrict₂ Finset.subset_union_left ⁻¹' S) + (Finset.restrict₂ Finset.subset_union_right ⁻¹' T) := by simp_rw [Set.disjoint_iff, subset_empty_iff, inter_cylinder, cylinder_eq_empty_iff] theorem IsClosed.cylinder [∀ i, TopologicalSpace (α i)] (s : Finset ι) {S : Set (∀ i : s, α i)} @@ -304,8 +302,8 @@ theorem inter_mem_measurableCylinders (hs : s ∈ measurableCylinders α) obtain ⟨s₂, S₂, hS₂, rfl⟩ := ht classical refine ⟨s₁ ∪ s₂, - (fun f ↦ (fun i ↦ f ⟨i, Finset.mem_union_left s₂ i.prop⟩ : ∀ i : s₁, α i)) ⁻¹' S₁ ∩ - {f | (fun i ↦ f ⟨i, Finset.mem_union_right s₁ i.prop⟩ : ∀ i : s₂, α i) ∈ S₂}, ?_, ?_⟩ + Finset.restrict₂ Finset.subset_union_left ⁻¹' S₁ ∩ + {f | Finset.restrict₂ Finset.subset_union_right f ∈ S₂}, ?_, ?_⟩ · refine MeasurableSet.inter ?_ ?_ · exact measurable_pi_lambda _ (fun _ ↦ measurable_pi_apply _) hS₁ · exact measurable_pi_lambda _ (fun _ ↦ measurable_pi_apply _) hS₂ @@ -353,7 +351,7 @@ theorem generateFrom_measurableCylinders : rintro t ht rfl refine ⟨{i}, {f | f ⟨i, Finset.mem_singleton_self i⟩ ∈ t i}, measurable_pi_apply _ (ht i), ?_⟩ ext1 x - simp only [singleton_pi, Function.eval, mem_preimage, mem_cylinder, mem_setOf_eq] + simp only [mem_preimage, Function.eval, mem_cylinder, mem_setOf_eq, Finset.restrict] end cylinders diff --git a/Mathlib/MeasureTheory/Constructions/Projective.lean b/Mathlib/MeasureTheory/Constructions/Projective.lean index 1b5505b2a390d..1754b6934c461 100644 --- a/Mathlib/MeasureTheory/Constructions/Projective.lean +++ b/Mathlib/MeasureTheory/Constructions/Projective.lean @@ -40,7 +40,7 @@ variable {ι : Type*} {α : ι → Type*} [∀ i, MeasurableSpace (α i)] the projection from `∀ i : I, α i` to `∀ i : J, α i` maps `P I` to `P J`. -/ def IsProjectiveMeasureFamily (P : ∀ J : Finset ι, Measure (∀ j : J, α j)) : Prop := ∀ (I J : Finset ι) (hJI : J ⊆ I), - P J = (P I).map (fun (x : ∀ i : I, α i) (j : J) ↦ x ⟨j, hJI j.2⟩) + P J = (P I).map (Finset.restrict₂ hJI) namespace IsProjectiveMeasureFamily @@ -51,7 +51,7 @@ lemma measure_univ_eq_of_subset (hP : IsProjectiveMeasureFamily P) (hJI : J ⊆ P I univ = P J univ := by classical have : (univ : Set (∀ i : I, α i)) = - (fun x : ∀ i : I, α i ↦ fun i : J ↦ x ⟨i, hJI i.2⟩) ⁻¹' (univ : Set (∀ i : J, α i)) := by + Finset.restrict₂ hJI ⁻¹' (univ : Set (∀ i : J, α i)) := by rw [preimage_univ] rw [this, ← Measure.map_apply _ MeasurableSet.univ] · rw [hP I J hJI] @@ -79,7 +79,7 @@ lemma congr_cylinder_of_subset (hP : IsProjectiveMeasureFamily P) have : (univ : Set ((j : {x // x ∈ ({i} : Finset ι)}) → α j)) = ∅ := by simp [hi_empty] simp [this] | inr h => - have : S = (fun f : ∀ i : I, α i ↦ fun j : J ↦ f ⟨j, hJI j.prop⟩) ⁻¹' T := + have : S = Finset.restrict₂ hJI ⁻¹' T := eq_of_cylinder_eq_of_subset h_eq hJI rw [hP I J hJI, Measure.map_apply _ hT, this] exact measurable_pi_lambda _ (fun _ ↦ measurable_pi_apply _) @@ -89,9 +89,8 @@ lemma congr_cylinder (hP : IsProjectiveMeasureFamily P) (h_eq : cylinder I S = cylinder J T) : P I S = P J T := by classical - let U := (fun f : ∀ i : (I ∪ J : Finset ι), α i - ↦ fun j : I ↦ f ⟨j, Finset.mem_union_left J j.prop⟩) ⁻¹' S ∩ - (fun f ↦ fun j : J ↦ f ⟨j, Finset.mem_union_right I j.prop⟩) ⁻¹' T + let U := Finset.restrict₂ Finset.subset_union_left ⁻¹' S ∩ + Finset.restrict₂ Finset.subset_union_right ⁻¹' T suffices P (I ∪ J) U = P I S ∧ P (I ∪ J) U = P J T from this.1.symm.trans this.2 constructor · have h_eq_union : cylinder I S = cylinder (I ∪ J) U := by @@ -107,7 +106,7 @@ end IsProjectiveMeasureFamily for all `I : Finset ι`, the projection from `∀ i, α i` to `∀ i : I, α i` maps `μ` to `P I`. -/ def IsProjectiveLimit (μ : Measure (∀ i, α i)) (P : ∀ J : Finset ι, Measure (∀ j : J, α j)) : Prop := - ∀ I : Finset ι, (μ.map fun x : ∀ i, α i ↦ fun i : I ↦ x i) = P I + ∀ I : Finset ι, (μ.map I.restrict) = P I namespace IsProjectiveLimit From d25f655df7b3bfe4a2235c4f7a5b766141a158dd Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:42:21 +0000 Subject: [PATCH 016/170] feat: add smul_prod lemmas (#8807) From #6718. --- .../BigOperators/GroupWithZero/Action.lean | 60 +++++++++++++++++-- .../Algebra/Polynomial/GroupRingAction.lean | 2 +- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean index 7ad7cb7f697d9..71d86a299d148 100644 --- a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean @@ -12,6 +12,13 @@ import Mathlib.Algebra.BigOperators.Finprod /-! # Lemmas about group actions on big operators +This file contains results about two kinds of actions: + +* sums over `DistribSMul`: `r • ∑ x ∈ s, f x = ∑ x ∈ s, r • f x` +* products over `MulDistribMulAction` (with primed name): `r • ∏ x ∈ s, f x = ∏ x ∈ s, r • f x` +* products over `SMulCommClass` (with unprimed name): + `b ^ s.card • ∏ x in s, f x = ∏ x in s, b • f x` + Note that analogous lemmas for `Module`s like `Finset.sum_smul` appear in other files. -/ @@ -31,7 +38,7 @@ section variable [Monoid α] [Monoid β] [MulDistribMulAction α β] -theorem List.smul_prod {r : α} {l : List β} : r • l.prod = (l.map (r • ·)).prod := +theorem List.smul_prod' {r : α} {l : List β} : r • l.prod = (l.map (r • ·)).prod := map_list_prod (MulDistribMulAction.toMonoidHom β r) l end @@ -53,17 +60,60 @@ section variable [Monoid α] [CommMonoid β] [MulDistribMulAction α β] -theorem Multiset.smul_prod {r : α} {s : Multiset β} : r • s.prod = (s.map (r • ·)).prod := +theorem Multiset.smul_prod' {r : α} {s : Multiset β} : r • s.prod = (s.map (r • ·)).prod := (MulDistribMulAction.toMonoidHom β r).map_multiset_prod s -theorem Finset.smul_prod {r : α} {f : γ → β} {s : Finset γ} : +theorem Finset.smul_prod' {r : α} {f : γ → β} {s : Finset γ} : (r • ∏ x ∈ s, f x) = ∏ x ∈ s, r • f x := map_prod (MulDistribMulAction.toMonoidHom β r) f s -theorem smul_finprod {ι : Sort*} [Finite ι] {f : ι → β} (r : α) : +theorem smul_finprod' {ι : Sort*} [Finite ι] {f : ι → β} (r : α) : r • ∏ᶠ x : ι, f x = ∏ᶠ x : ι, r • (f x) := by cases nonempty_fintype (PLift ι) simp only [finprod_eq_prod_plift_of_mulSupport_subset (s := Finset.univ) (by simp), - finprod_eq_prod_of_fintype, Finset.smul_prod] + finprod_eq_prod_of_fintype, Finset.smul_prod'] end + +namespace List + +@[to_additive] +theorem smul_prod [Monoid α] [Monoid β] [MulAction α β] [IsScalarTower α β β] [SMulCommClass α β β] + (l : List β) (m : α) : + m ^ l.length • l.prod = (l.map (m • ·)).prod := by + induction l with + | nil => simp + | cons head tail ih => simp [← ih, smul_mul_smul_comm, pow_succ'] + +end List + +namespace Multiset + +@[to_additive] +theorem smul_prod [Monoid α] [CommMonoid β] [MulAction α β] [IsScalarTower α β β] + [SMulCommClass α β β] (s : Multiset β) (b : α) : + b ^ card s • s.prod = (s.map (b • ·)).prod := + Quot.induction_on s <| by simp [List.smul_prod] + +end Multiset + +namespace Finset + +theorem smul_prod + [CommMonoid β] [Monoid α] [MulAction α β] [IsScalarTower α β β] [SMulCommClass α β β] + (s : Finset β) (b : α) (f : β → β) : + b ^ s.card • ∏ x in s, f x = ∏ x in s, b • f x := by + have : Multiset.map (fun (x : β) ↦ b • f x) s.val = + Multiset.map (fun x ↦ b • x) (Multiset.map (fun x ↦ f x) s.val) := by + simp only [Multiset.map_map, Function.comp_apply] + simp_rw [prod_eq_multiset_prod, card_def, this, ← Multiset.smul_prod _ b, Multiset.card_map] + +theorem prod_smul + [CommMonoid β] [CommMonoid α] [MulAction α β] [IsScalarTower α β β] [SMulCommClass α β β] + (s : Finset β) (b : β → α) (f : β → β) : + ∏ i in s, b i • f i = (∏ i in s, b i) • ∏ i in s, f i := by + induction s using Finset.cons_induction_on with + | h₁ => simp + | h₂ hj ih => rw [prod_cons, ih, smul_mul_smul_comm, ← prod_cons hj, ← prod_cons hj] + +end Finset diff --git a/Mathlib/Algebra/Polynomial/GroupRingAction.lean b/Mathlib/Algebra/Polynomial/GroupRingAction.lean index 30813c8edd473..586acacc30c03 100644 --- a/Mathlib/Algebra/Polynomial/GroupRingAction.lean +++ b/Mathlib/Algebra/Polynomial/GroupRingAction.lean @@ -95,7 +95,7 @@ theorem prodXSubSMul.eval (x : R) : (prodXSubSMul G R x).eval x = 0 := theorem prodXSubSMul.smul (x : R) (g : G) : g • prodXSubSMul G R x = prodXSubSMul G R x := letI := Classical.decEq R - Finset.smul_prod.trans <| + Finset.smul_prod'.trans <| Fintype.prod_bijective _ (MulAction.bijective g) _ _ fun g' ↦ by rw [ofQuotientStabilizer_smul, smul_sub, Polynomial.smul_X, Polynomial.smul_C] From f85eaad5f715160794d6a5e665fe9c38988ac4d1 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 18 Sep 2024 11:42:22 +0000 Subject: [PATCH 017/170] feat(MeasureTheory): generalize `measure_iUnion_eq_iSup` (#16390) --- .../Decomposition/UnsignedHahn.lean | 3 +- Mathlib/MeasureTheory/Integral/Lebesgue.lean | 3 +- .../MeasureTheory/Integral/SetIntegral.lean | 2 +- .../MeasureTheory/Measure/MeasureSpace.lean | 193 +++++++++--------- Mathlib/MeasureTheory/Measure/Regular.lean | 16 +- Mathlib/MeasureTheory/Measure/Restrict.lean | 2 +- .../Kernel/Disintegration/CDFToKernel.lean | 2 +- .../Kernel/Disintegration/CondCDF.lean | 6 +- .../Kernel/Disintegration/Density.lean | 15 +- Mathlib/Probability/StrongLaw.lean | 2 +- 10 files changed, 117 insertions(+), 127 deletions(-) diff --git a/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean index 8ff30acf7423c..1e85f61f04295 100644 --- a/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean @@ -49,7 +49,8 @@ theorem hahn_decomposition [IsFiniteMeasure μ] [IsFiniteMeasure ν] : have d_Union (s : ℕ → Set α) (hm : Monotone s) : Tendsto (fun n => d (s n)) atTop (𝓝 (d (⋃ n, s n))) := by refine Tendsto.sub ?_ ?_ <;> - refine NNReal.tendsto_coe.2 <| (ENNReal.tendsto_toNNReal ?_).comp <| tendsto_measure_iUnion hm + refine NNReal.tendsto_coe.2 <| (ENNReal.tendsto_toNNReal ?_).comp <| + tendsto_measure_iUnion_atTop hm · exact hμ _ · exact hν _ have d_Inter (s : ℕ → Set α) (hs : ∀ n, MeasurableSet (s n)) (hm : ∀ n m, n ≤ m → s m ⊆ s n) : diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index cc0f07957494b..4b2e98b074018 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -385,8 +385,7 @@ theorem lintegral_iSup {f : ℕ → α → ℝ≥0∞} (hf : ∀ n, Measurable ( _ = ∑ r ∈ (rs.map c).range, r * μ (⋃ n, rs.map c ⁻¹' {r} ∩ { a | r ≤ f n a }) := by simp only [(eq _).symm] _ = ∑ r ∈ (rs.map c).range, ⨆ n, r * μ (rs.map c ⁻¹' {r} ∩ { a | r ≤ f n a }) := - (Finset.sum_congr rfl fun x _ => by - rw [measure_iUnion_eq_iSup (mono x).directed_le, ENNReal.mul_iSup]) + Finset.sum_congr rfl fun x _ => by rw [(mono x).measure_iUnion, ENNReal.mul_iSup] _ = ⨆ n, ∑ r ∈ (rs.map c).range, r * μ (rs.map c ⁻¹' {r} ∩ { a | r ≤ f n a }) := by refine ENNReal.finsetSum_iSup_of_monotone fun p i j h ↦ ?_ gcongr _ * μ ?_ diff --git a/Mathlib/MeasureTheory/Integral/SetIntegral.lean b/Mathlib/MeasureTheory/Integral/SetIntegral.lean index eebb4d8f3b6bf..38f00f6fd9293 100644 --- a/Mathlib/MeasureTheory/Integral/SetIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/SetIntegral.lean @@ -228,7 +228,7 @@ theorem tendsto_setIntegral_of_monotone {ι : Type*} [Countable ι] [Semilattice refine Metric.nhds_basis_closedBall.tendsto_right_iff.2 fun ε ε0 => ?_ lift ε to ℝ≥0 using ε0.le have : ∀ᶠ i in atTop, ν (s i) ∈ Icc (ν S - ε) (ν S + ε) := - tendsto_measure_iUnion h_mono (ENNReal.Icc_mem_nhds hfi'.ne (ENNReal.coe_pos.2 ε0).ne') + tendsto_measure_iUnion_atTop h_mono (ENNReal.Icc_mem_nhds hfi'.ne (ENNReal.coe_pos.2 ε0).ne') filter_upwards [this] with i hi rw [mem_closedBall_iff_norm', ← integral_diff (hsm i) hfi hsub, ← coe_nnnorm, NNReal.coe_le_coe, ← ENNReal.coe_le_coe] diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index ddd5a28be1892..f09889ada8f6b 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -7,6 +7,7 @@ import Mathlib.MeasureTheory.Measure.NullMeasurable import Mathlib.MeasureTheory.MeasurableSpace.Embedding import Mathlib.MeasureTheory.OuterMeasure.BorelCantelli import Mathlib.Topology.Algebra.Order.LiminfLimsup +import Mathlib.Order.Interval.Set.Monotone /-! # Measure spaces @@ -311,14 +312,15 @@ theorem ae_eq_of_subset_of_measure_ge (h₁ : s ⊆ t) (h₂ : μ t ≤ μ s) (h (ht : μ t ≠ ∞) : s =ᵐ[μ] t := ae_eq_of_ae_subset_of_measure_ge (HasSubset.Subset.eventuallyLE h₁) h₂ hsm ht -theorem measure_iUnion_congr_of_subset [Countable β] {s : β → Set α} {t : β → Set α} - (hsub : ∀ b, s b ⊆ t b) (h_le : ∀ b, μ (t b) ≤ μ (s b)) : μ (⋃ b, s b) = μ (⋃ b, t b) := by - rcases Classical.em (∃ b, μ (t b) = ∞) with (⟨b, hb⟩ | htop) +theorem measure_iUnion_congr_of_subset {ι : Sort*} [Countable ι] {s : ι → Set α} {t : ι → Set α} + (hsub : ∀ i, s i ⊆ t i) (h_le : ∀ i, μ (t i) ≤ μ (s i)) : μ (⋃ i, s i) = μ (⋃ i, t i) := by + refine le_antisymm (by gcongr; apply hsub) ?_ + rcases Classical.em (∃ i, μ (t i) = ∞) with (⟨i, hi⟩ | htop) · calc - μ (⋃ b, s b) = ∞ := top_unique (hb ▸ (h_le b).trans <| measure_mono <| subset_iUnion _ _) - _ = μ (⋃ b, t b) := Eq.symm <| top_unique <| hb ▸ measure_mono (subset_iUnion _ _) + μ (⋃ i, t i) ≤ ∞ := le_top + _ ≤ μ (s i) := hi ▸ h_le i + _ ≤ μ (⋃ i, s i) := measure_mono <| subset_iUnion _ _ push_neg at htop - refine le_antisymm (measure_mono (iUnion_mono hsub)) ?_ set M := toMeasurable μ have H : ∀ b, (M (t b) ∩ M (⋃ b, s b) : Set α) =ᵐ[μ] M (t b) := by refine fun b => ae_eq_of_subset_of_measure_ge inter_subset_left ?_ ?_ ?_ @@ -344,11 +346,10 @@ theorem measure_union_congr_of_subset {t₁ t₂ : Set α} (hs : s₁ ⊆ s₂) exact measure_iUnion_congr_of_subset (Bool.forall_bool.2 ⟨ht, hs⟩) (Bool.forall_bool.2 ⟨htμ, hsμ⟩) @[simp] -theorem measure_iUnion_toMeasurable [Countable β] (s : β → Set α) : - μ (⋃ b, toMeasurable μ (s b)) = μ (⋃ b, s b) := - Eq.symm <| - measure_iUnion_congr_of_subset (fun _b => subset_toMeasurable _ _) fun _b => - (measure_toMeasurable _).le +theorem measure_iUnion_toMeasurable {ι : Sort*} [Countable ι] (s : ι → Set α) : + μ (⋃ i, toMeasurable μ (s i)) = μ (⋃ i, s i) := + Eq.symm <| measure_iUnion_congr_of_subset (fun _i => subset_toMeasurable _ _) fun _i ↦ + (measure_toMeasurable _).le theorem measure_biUnion_toMeasurable {I : Set β} (hc : I.Countable) (s : β → Set α) : μ (⋃ b ∈ I, toMeasurable μ (s b)) = μ (⋃ b ∈ I, s b) := by @@ -420,30 +421,28 @@ theorem nonempty_inter_of_measure_lt_add' {m : MeasurableSpace α} (μ : Measure rw [inter_comm] exact nonempty_inter_of_measure_lt_add μ hs h't h's h -/-- Continuity from below: the measure of the union of a directed sequence of (not necessarily --measurable) sets is the supremum of the measures. -/ -theorem measure_iUnion_eq_iSup [Countable ι] {s : ι → Set α} (hd : Directed (· ⊆ ·) s) : +/-- Continuity from below: +the measure of the union of a directed sequence of (not necessarily measurable) sets +is the supremum of the measures. -/ +theorem _root_.Directed.measure_iUnion [Countable ι] {s : ι → Set α} (hd : Directed (· ⊆ ·) s) : μ (⋃ i, s i) = ⨆ i, μ (s i) := by - cases nonempty_encodable ι -- WLOG, `ι = ℕ` - generalize ht : Function.extend Encodable.encode s ⊥ = t - replace hd : Directed (· ⊆ ·) t := ht ▸ hd.extend_bot Encodable.encode_injective + rcases Countable.exists_injective_nat ι with ⟨e, he⟩ + generalize ht : Function.extend e s ⊥ = t + replace hd : Directed (· ⊆ ·) t := ht ▸ hd.extend_bot he suffices μ (⋃ n, t n) = ⨆ n, μ (t n) by - simp only [← ht, Function.apply_extend μ, ← iSup_eq_iUnion, - iSup_extend_bot Encodable.encode_injective, Function.comp_def, Pi.bot_apply, bot_eq_empty, - measure_empty] at this - exact this.trans (iSup_extend_bot Encodable.encode_injective _) + simp only [← ht, Function.apply_extend μ, ← iSup_eq_iUnion, iSup_extend_bot he, + Function.comp_def, Pi.bot_apply, bot_eq_empty, measure_empty] at this + exact this.trans (iSup_extend_bot he _) clear! ι -- The `≥` inequality is trivial - refine le_antisymm ?_ (iSup_le fun i => measure_mono <| subset_iUnion _ _) + refine le_antisymm ?_ (iSup_le fun i ↦ measure_mono <| subset_iUnion _ _) -- Choose `T n ⊇ t n` of the same measure, put `Td n = disjointed T` set T : ℕ → Set α := fun n => toMeasurable μ (t n) set Td : ℕ → Set α := disjointed T - have hm : ∀ n, MeasurableSet (Td n) := - MeasurableSet.disjointed fun n => measurableSet_toMeasurable _ _ + have hm : ∀ n, MeasurableSet (Td n) := .disjointed fun n ↦ measurableSet_toMeasurable _ _ calc - μ (⋃ n, t n) ≤ μ (⋃ n, T n) := measure_mono (iUnion_mono fun i => subset_toMeasurable _ _) - _ = μ (⋃ n, Td n) := by rw [iUnion_disjointed] + μ (⋃ n, t n) = μ (⋃ n, Td n) := by rw [iUnion_disjointed, measure_iUnion_toMeasurable] _ ≤ ∑' n, μ (Td n) := measure_iUnion_le _ _ = ⨆ I : Finset ℕ, ∑ n ∈ I, μ (Td n) := ENNReal.tsum_eq_iSup_sum _ ≤ ⨆ n, μ (t n) := iSup_le fun I => by @@ -456,23 +455,48 @@ theorem measure_iUnion_eq_iSup [Countable ι] {s : ι → Set α} (hd : Directed _ ≤ μ (t N) := measure_mono (iUnion₂_subset hN) _ ≤ ⨆ n, μ (t n) := le_iSup (μ ∘ t) N +@[deprecated (since := "2024-09-01")] alias measure_iUnion_eq_iSup := Directed.measure_iUnion + +/-- Continuity from below: +the measure of the union of a monotone family of sets is equal to the supremum of their measures. +The theorem assumes that the `atTop` filter on the index set is countably generated, +so it works for a family indexed by a countable type, as well as `ℝ`. -/ +theorem _root_.Monotone.measure_iUnion [Preorder ι] [IsDirected ι (· ≤ ·)] + [(atTop : Filter ι).IsCountablyGenerated] {s : ι → Set α} (hs : Monotone s) : + μ (⋃ i, s i) = ⨆ i, μ (s i) := by + refine le_antisymm ?_ (iSup_le fun i ↦ measure_mono <| subset_iUnion _ _) + cases isEmpty_or_nonempty ι with + | inl _ => simp + | inr _ => + rcases exists_seq_monotone_tendsto_atTop_atTop ι with ⟨x, hxm, hx⟩ + calc + μ (⋃ i, s i) ≤ μ (⋃ n, s (x n)) := by + refine measure_mono <| iUnion_mono' fun i ↦ ?_ + rcases (hx.eventually_ge_atTop i).exists with ⟨n, hn⟩ + exact ⟨n, hs hn⟩ + _ = ⨆ n, μ (s (x n)) := (hs.comp hxm).directed_le.measure_iUnion + _ ≤ ⨆ i, μ (s i) := iSup_comp_le (μ ∘ s) x + +theorem _root_.Antitone.measure_iUnion [Preorder ι] [IsDirected ι (· ≥ ·)] + [(atBot : Filter ι).IsCountablyGenerated] {s : ι → Set α} (hs : Antitone s) : + μ (⋃ i, s i) = ⨆ i, μ (s i) := + hs.dual_left.measure_iUnion + /-- Continuity from below: the measure of the union of a sequence of (not necessarily measurable) sets is the supremum of the measures of the partial unions. -/ -theorem measure_iUnion_eq_iSup' {α ι : Type*} [MeasurableSpace α] {μ : Measure α} - [Countable ι] [Preorder ι] [IsDirected ι (· ≤ ·)] - {f : ι → Set α} : μ (⋃ i, f i) = ⨆ i, μ (Accumulate f i) := by - have hd : Directed (· ⊆ ·) (Accumulate f) := by - intro i j - rcases directed_of (· ≤ ·) i j with ⟨k, rik, rjk⟩ - exact ⟨k, biUnion_subset_biUnion_left fun l rli ↦ le_trans rli rik, - biUnion_subset_biUnion_left fun l rlj ↦ le_trans rlj rjk⟩ +theorem measure_iUnion_eq_iSup_accumulate [Preorder ι] [IsDirected ι (· ≤ ·)] + [(atTop : Filter ι).IsCountablyGenerated] {f : ι → Set α} : + μ (⋃ i, f i) = ⨆ i, μ (Accumulate f i) := by rw [← iUnion_accumulate] - exact measure_iUnion_eq_iSup hd + exact monotone_accumulate.measure_iUnion + +@[deprecated (since := "2024-09-01")] +alias measure_iUnion_eq_iSup' := measure_iUnion_eq_iSup_accumulate theorem measure_biUnion_eq_iSup {s : ι → Set α} {t : Set ι} (ht : t.Countable) (hd : DirectedOn ((· ⊆ ·) on s) t) : μ (⋃ i ∈ t, s i) = ⨆ i ∈ t, μ (s i) := by - haveI := ht.toEncodable - rw [biUnion_eq_iUnion, measure_iUnion_eq_iSup hd.directed_val, ← iSup_subtype''] + haveI := ht.to_subtype + rw [biUnion_eq_iUnion, hd.directed_val.measure_iUnion, ← iSup_subtype''] /-- Continuity from above: the measure of the intersection of a decreasing sequence of measurable sets is the infimum of the measures. -/ @@ -483,7 +507,7 @@ theorem measure_iInter_eq_iInf [Countable ι] {s : ι → Set α} (h : ∀ i, Nu rw [← ENNReal.sub_sub_cancel hk (iInf_le _ k), ENNReal.sub_iInf, ← ENNReal.sub_sub_cancel hk (measure_mono (iInter_subset _ k)), ← measure_diff (iInter_subset _ k) (.iInter h) (this _ (iInter_subset _ k)), - diff_iInter, measure_iUnion_eq_iSup] + diff_iInter, Directed.measure_iUnion] · congr 1 refine le_antisymm (iSup_mono' fun i => ?_) (iSup_mono fun i => le_measure_diff) rcases hd i k with ⟨j, hji, hjk⟩ @@ -519,19 +543,31 @@ theorem measure_iInter_eq_iInf' {α ι : Type*} [MeasurableSpace α] {μ : Measu /-- Continuity from below: the measure of the union of an increasing sequence of (not necessarily measurable) sets is the limit of the measures. -/ -theorem tendsto_measure_iUnion [Preorder ι] [IsDirected ι (· ≤ ·)] [Countable ι] - {s : ι → Set α} (hm : Monotone s) : Tendsto (μ ∘ s) atTop (𝓝 (μ (⋃ n, s n))) := by - rw [measure_iUnion_eq_iSup hm.directed_le] +theorem tendsto_measure_iUnion_atTop [Preorder ι] [IsDirected ι (· ≤ ·)] + [IsCountablyGenerated (atTop : Filter ι)] {s : ι → Set α} (hm : Monotone s) : + Tendsto (μ ∘ s) atTop (𝓝 (μ (⋃ n, s n))) := by + rw [hm.measure_iUnion] exact tendsto_atTop_iSup fun n m hnm => measure_mono <| hm hnm +@[deprecated (since := "2024-09-01")] alias tendsto_measure_iUnion := tendsto_measure_iUnion_atTop + +theorem tendsto_measure_iUnion_atBot [Preorder ι] [IsDirected ι (· ≥ ·)] + [IsCountablyGenerated (atBot : Filter ι)] {s : ι → Set α} (hm : Antitone s) : + Tendsto (μ ∘ s) atBot (𝓝 (μ (⋃ n, s n))) := + tendsto_measure_iUnion_atTop (ι := ιᵒᵈ) hm.dual_left + /-- Continuity from below: the measure of the union of a sequence of (not necessarily measurable) sets is the limit of the measures of the partial unions. -/ -theorem tendsto_measure_iUnion' {α ι : Type*} [MeasurableSpace α] {μ : Measure α} [Countable ι] - [Preorder ι] [IsDirected ι (· ≤ ·)] {f : ι → Set α} : +theorem tendsto_measure_iUnion_accumulate {α ι : Type*} + [Preorder ι] [IsDirected ι (· ≤ ·)] [IsCountablyGenerated (atTop : Filter ι)] + [MeasurableSpace α] {μ : Measure α} {f : ι → Set α} : Tendsto (fun i ↦ μ (Accumulate f i)) atTop (𝓝 (μ (⋃ i, f i))) := by - rw [measure_iUnion_eq_iSup'] + rw [measure_iUnion_eq_iSup_accumulate] exact tendsto_atTop_iSup fun i j hij ↦ by gcongr +@[deprecated (since := "2024-09-01")] +alias tendsto_measure_iUnion' := tendsto_measure_iUnion_accumulate + /-- Continuity from above: the measure of the intersection of a decreasing sequence of measurable sets is the limit of the measures. -/ theorem tendsto_measure_iInter [Countable ι] [Preorder ι] [IsDirected ι (· ≤ ·)] {s : ι → Set α} @@ -1794,61 +1830,28 @@ theorem biSup_measure_Iic [Preorder α] {s : Set α} (hsc : s.Countable) exact iUnion₂_eq_univ_iff.2 hst · exact directedOn_iff_directed.2 (hdir.directed_val.mono_comp _ fun x y => Iic_subset_Iic.2) -theorem tendsto_measure_Ico_atTop [SemilatticeSup α] [NoMaxOrder α] +theorem tendsto_measure_Ico_atTop [Preorder α] [IsDirected α (· ≤ ·)] [NoMaxOrder α] [(atTop : Filter α).IsCountablyGenerated] (μ : Measure α) (a : α) : Tendsto (fun x => μ (Ico a x)) atTop (𝓝 (μ (Ici a))) := by - haveI : Nonempty α := ⟨a⟩ - have h_mono : Monotone fun x => μ (Ico a x) := fun i j hij => by simp only; gcongr - convert tendsto_atTop_iSup h_mono - obtain ⟨xs, hxs_mono, hxs_tendsto⟩ := exists_seq_monotone_tendsto_atTop_atTop α - have h_Ici : Ici a = ⋃ n, Ico a (xs n) := by - ext1 x - simp only [mem_Ici, mem_iUnion, mem_Ico, exists_and_left, iff_self_and] - intro - obtain ⟨y, hxy⟩ := NoMaxOrder.exists_gt x - obtain ⟨n, hn⟩ := tendsto_atTop_atTop.mp hxs_tendsto y - exact ⟨n, hxy.trans_le (hn n le_rfl)⟩ - rw [h_Ici, measure_iUnion_eq_iSup, iSup_eq_iSup_subseq_of_monotone h_mono hxs_tendsto] - exact Monotone.directed_le fun i j hij => Ico_subset_Ico_right (hxs_mono hij) - -theorem tendsto_measure_Ioc_atBot [SemilatticeInf α] [NoMinOrder α] + rw [← iUnion_Ico_right] + exact tendsto_measure_iUnion_atTop (antitone_const.Ico monotone_id) + +theorem tendsto_measure_Ioc_atBot [Preorder α] [IsDirected α (· ≥ ·)] [NoMinOrder α] [(atBot : Filter α).IsCountablyGenerated] (μ : Measure α) (a : α) : Tendsto (fun x => μ (Ioc x a)) atBot (𝓝 (μ (Iic a))) := by - haveI : Nonempty α := ⟨a⟩ - have h_mono : Antitone fun x => μ (Ioc x a) := fun i j hij => by simp only; gcongr - convert tendsto_atBot_iSup h_mono - obtain ⟨xs, hxs_mono, hxs_tendsto⟩ := exists_seq_antitone_tendsto_atTop_atBot α - have h_Iic : Iic a = ⋃ n, Ioc (xs n) a := by - ext1 x - simp only [mem_Iic, mem_iUnion, mem_Ioc, exists_and_right, iff_and_self] - intro - obtain ⟨y, hxy⟩ := NoMinOrder.exists_lt x - obtain ⟨n, hn⟩ := tendsto_atTop_atBot.mp hxs_tendsto y - exact ⟨n, (hn n le_rfl).trans_lt hxy⟩ - rw [h_Iic, measure_iUnion_eq_iSup, iSup_eq_iSup_subseq_of_antitone h_mono hxs_tendsto] - exact Monotone.directed_le fun i j hij => Ioc_subset_Ioc_left (hxs_mono hij) - -theorem tendsto_measure_Iic_atTop [SemilatticeSup α] [(atTop : Filter α).IsCountablyGenerated] - (μ : Measure α) : Tendsto (fun x => μ (Iic x)) atTop (𝓝 (μ univ)) := by - cases isEmpty_or_nonempty α - · have h1 : ∀ x : α, Iic x = ∅ := fun x => Subsingleton.elim _ _ - have h2 : (univ : Set α) = ∅ := Subsingleton.elim _ _ - simp_rw [h1, h2] - exact tendsto_const_nhds - have h_mono : Monotone fun x => μ (Iic x) := fun i j hij => by simp only; gcongr - convert tendsto_atTop_iSup h_mono - obtain ⟨xs, hxs_mono, hxs_tendsto⟩ := exists_seq_monotone_tendsto_atTop_atTop α - have h_univ : (univ : Set α) = ⋃ n, Iic (xs n) := by - ext1 x - simp only [mem_univ, mem_iUnion, mem_Iic, true_iff] - obtain ⟨n, hn⟩ := tendsto_atTop_atTop.mp hxs_tendsto x - exact ⟨n, hn n le_rfl⟩ - rw [h_univ, measure_iUnion_eq_iSup, iSup_eq_iSup_subseq_of_monotone h_mono hxs_tendsto] - exact Monotone.directed_le fun i j hij => Iic_subset_Iic.mpr (hxs_mono hij) - -theorem tendsto_measure_Ici_atBot [SemilatticeInf α] [h : (atBot : Filter α).IsCountablyGenerated] - (μ : Measure α) : Tendsto (fun x => μ (Ici x)) atBot (𝓝 (μ univ)) := - @tendsto_measure_Iic_atTop αᵒᵈ _ _ h μ + rw [← iUnion_Ioc_left] + exact tendsto_measure_iUnion_atBot (monotone_id.Ioc antitone_const) + +theorem tendsto_measure_Iic_atTop [Preorder α] [IsDirected α (· ≤ ·)] + [(atTop : Filter α).IsCountablyGenerated] (μ : Measure α) : + Tendsto (fun x => μ (Iic x)) atTop (𝓝 (μ univ)) := by + rw [← iUnion_Iic] + exact tendsto_measure_iUnion_atTop monotone_Iic + +theorem tendsto_measure_Ici_atBot [Preorder α] [IsDirected α (· ≥ ·)] + [(atBot : Filter α).IsCountablyGenerated] (μ : Measure α) : + Tendsto (fun x => μ (Ici x)) atBot (𝓝 (μ univ)) := + tendsto_measure_Iic_atTop (α := αᵒᵈ) μ variable [PartialOrder α] {a b : α} diff --git a/Mathlib/MeasureTheory/Measure/Regular.lean b/Mathlib/MeasureTheory/Measure/Regular.lean index c5103e960fc42..362b5a971e2a4 100644 --- a/Mathlib/MeasureTheory/Measure/Regular.lean +++ b/Mathlib/MeasureTheory/Measure/Regular.lean @@ -457,8 +457,7 @@ lemma of_restrict {μ : Measure α} {s : ℕ → Set α} intro F hF r hr have hBU : ⋃ n, F ∩ s n = F := by rw [← inter_iUnion, univ_subset_iff.mp hs, inter_univ] have : μ F = ⨆ n, μ (F ∩ s n) := by - rw [← measure_iUnion_eq_iSup, hBU] - exact Monotone.directed_le fun m n h ↦ inter_subset_inter_right _ (hmono h) + rw [← (monotone_const.inter hmono).measure_iUnion, hBU] rw [this] at hr rcases lt_iSup_iff.1 hr with ⟨n, hn⟩ rw [← restrict_apply hF] at hn @@ -509,8 +508,7 @@ lemma of_sigmaFinite [SigmaFinite μ] : set B : ℕ → Set α := spanningSets μ have hBU : ⋃ n, s ∩ B n = s := by rw [← inter_iUnion, iUnion_spanningSets, inter_univ] have : μ s = ⨆ n, μ (s ∩ B n) := by - rw [← measure_iUnion_eq_iSup, hBU] - exact Monotone.directed_le fun m n h => inter_subset_inter_right _ (monotone_spanningSets μ h) + rw [← (monotone_const.inter (monotone_spanningSets μ)).measure_iUnion, hBU] rw [this] at hr rcases lt_iSup_iff.1 hr with ⟨n, hn⟩ refine ⟨s ∩ B n, inter_subset_left, ⟨hs.inter (measurable_spanningSets μ n), ?_⟩, hn⟩ @@ -617,7 +615,7 @@ theorem of_pseudoMetrizableSpace {X : Type*} [TopologicalSpace X] [PseudoMetriza let A : PseudoMetricSpace X := TopologicalSpace.pseudoMetrizableSpacePseudoMetric X intro U hU r hr rcases hU.exists_iUnion_isClosed with ⟨F, F_closed, -, rfl, F_mono⟩ - rw [measure_iUnion_eq_iSup F_mono.directed_le] at hr + rw [F_mono.measure_iUnion] at hr rcases lt_iSup_iff.1 hr with ⟨n, hn⟩ exact ⟨F n, subset_iUnion _ _, F_closed n, hn⟩ @@ -629,8 +627,8 @@ theorem isCompact_isClosed {X : Type*} [TopologicalSpace X] [SigmaCompactSpace X have hBc : ∀ n, IsCompact (F ∩ B n) := fun n => (isCompact_compactCovering X n).inter_left hF have hBU : ⋃ n, F ∩ B n = F := by rw [← inter_iUnion, iUnion_compactCovering, Set.inter_univ] have : μ F = ⨆ n, μ (F ∩ B n) := by - rw [← measure_iUnion_eq_iSup, hBU] - exact Monotone.directed_le fun m n h => inter_subset_inter_right _ (compactCovering_subset _ h) + rw [← Monotone.measure_iUnion, hBU] + exact monotone_const.inter monotone_accumulate rw [this] at hr rcases lt_iSup_iff.1 hr with ⟨n, hn⟩ exact ⟨_, inter_subset_left, hBc n, hn⟩ @@ -1051,8 +1049,8 @@ instance (priority := 100) {X : Type*} [TopologicalSpace X] [PseudoMetrizableSpace X] [SigmaCompactSpace X] [MeasurableSpace X] [BorelSpace X] (μ : Measure X) [SigmaFinite μ] : InnerRegular μ := by refine ⟨(InnerRegularWRT.isCompact_isClosed μ).trans ?_⟩ - refine InnerRegularWRT.of_restrict (fun n ↦ ?_) - (univ_subset_iff.2 (iUnion_spanningSets μ)) (monotone_spanningSets μ) + refine InnerRegularWRT.of_restrict (fun n ↦ ?_) (iUnion_spanningSets μ).superset + (monotone_spanningSets μ) have : Fact (μ (spanningSets μ n) < ∞) := ⟨measure_spanningSets_lt_top μ n⟩ exact WeaklyRegular.innerRegular_measurable.trans InnerRegularWRT.of_sigmaFinite diff --git a/Mathlib/MeasureTheory/Measure/Restrict.lean b/Mathlib/MeasureTheory/Measure/Restrict.lean index 713ef07032fc3..5e3e7702c9a7e 100644 --- a/Mathlib/MeasureTheory/Measure/Restrict.lean +++ b/Mathlib/MeasureTheory/Measure/Restrict.lean @@ -281,7 +281,7 @@ theorem restrict_iUnion_apply [Countable ι] {s : ι → Set α} (hd : Pairwise theorem restrict_iUnion_apply_eq_iSup [Countable ι] {s : ι → Set α} (hd : Directed (· ⊆ ·) s) {t : Set α} (ht : MeasurableSet t) : μ.restrict (⋃ i, s i) t = ⨆ i, μ.restrict (s i) t := by simp only [restrict_apply ht, inter_iUnion] - rw [measure_iUnion_eq_iSup] + rw [Directed.measure_iUnion] exacts [hd.mono_comp _ fun s₁ s₂ => inter_subset_inter_right _] /-- The restriction of the pushforward measure is the pushforward of the restriction. For a version diff --git a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean index 9c1e0f3f8b320..5b8e36ae7d2f4 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean @@ -550,7 +550,7 @@ lemma setLIntegral_toKernel_univ [IsFiniteKernel κ] (hf : IsCondKernelCDF f κ refine Monotone.directed_le fun i j hij ↦ ?_ refine prod_subset_prod_iff.mpr (Or.inl ⟨subset_rfl, Iic_subset_Iic.mpr ?_⟩) exact mod_cast hij - simp_rw [measure_iUnion_eq_iSup h_dir, measure_iUnion_eq_iSup h_dir_prod] + simp_rw [h_dir.measure_iUnion, h_dir_prod.measure_iUnion] rw [lintegral_iSup_directed] · simp_rw [setLIntegral_toKernel_Iic hf _ _ hs] · refine fun q ↦ Measurable.aemeasurable ?_ diff --git a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean index 4b5aac1603122..22bfd49d0e410 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean @@ -78,10 +78,8 @@ theorem tendsto_IicSnd_atTop {s : Set α} (hs : MeasurableSet s) : Tendsto (fun r : ℚ ↦ ρ.IicSnd r s) atTop (𝓝 (ρ.fst s)) := by simp_rw [ρ.IicSnd_apply _ hs, fst_apply hs, ← prod_univ] rw [← Real.iUnion_Iic_rat, prod_iUnion] - refine tendsto_measure_iUnion fun r q hr_le_q x ↦ ?_ - simp only [mem_prod, mem_Iic, and_imp] - refine fun hxs hxr ↦ ⟨hxs, hxr.trans ?_⟩ - exact mod_cast hr_le_q + apply tendsto_measure_iUnion_atTop + exact monotone_const.set_prod Rat.cast_mono.Iic theorem tendsto_IicSnd_atBot [IsFiniteMeasure ρ] {s : Set α} (hs : MeasurableSet s) : Tendsto (fun r : ℚ ↦ ρ.IicSnd r s) atBot (𝓝 0) := by diff --git a/Mathlib/Probability/Kernel/Disintegration/Density.lean b/Mathlib/Probability/Kernel/Disintegration/Density.lean index 77a32c6fbfe53..1e1d4fe17ac12 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Density.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Density.lean @@ -656,11 +656,8 @@ lemma tendsto_integral_density_of_monotone (hκν : fst κ ≤ ν) [IsFiniteKern · simp only [mem_Iio] exact ENNReal.lt_add_right (measure_ne_top _ _) one_ne_zero refine h_cont.tendsto.comp ?_ - have h := tendsto_measure_iUnion (s := fun m ↦ univ ×ˢ seq m) (μ := κ a) ?_ - swap; · intro n m hnm x; simp only [mem_prod, mem_univ, true_and]; exact fun h ↦ hseq hnm h - convert h - rw [← prod_iUnion, hseq_iUnion] - simp only [univ_prod_univ, measure_univ] + convert tendsto_measure_iUnion_atTop (monotone_const.set_prod hseq) + rw [← prod_iUnion, hseq_iUnion, univ_prod_univ] lemma tendsto_integral_density_of_antitone (hκν : fst κ ≤ ν) [IsFiniteKernel ν] (a : α) (seq : ℕ → Set β) (hseq : Antitone seq) (hseq_iInter : ⋂ i, seq i = ∅) @@ -776,13 +773,7 @@ lemma tendsto_densityProcess_fst_atTop_univ_of_monotone (κ : Kernel α (γ × simp only [mem_prod, mem_setOf_eq, and_imp] exact fun h _ ↦ h refine ENNReal.Tendsto.div_const ?_ ?_ - · have h := tendsto_measure_iUnion (μ := κ a) - (s := fun m ↦ countablePartitionSet n x ×ˢ seq m) ?_ - swap - · intro m m' hmm' - simp only [le_eq_subset, prod_subset_prod_iff, subset_rfl, true_and] - exact Or.inl <| hseq hmm' - convert h + · convert tendsto_measure_iUnion_atTop (monotone_const.set_prod hseq) rw [← prod_iUnion, hseq_iUnion] · exact Or.inr h0 diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index 24a5607e58036..95e1a9132d2a8 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -298,7 +298,7 @@ theorem tsum_prob_mem_Ioi_lt_top {X : Ω → ℝ} (hint : Integrable X) (hnonneg · simp (config := {contextual := true}) only [Set.mem_Ioc, Set.mem_Ioi, Set.iUnion_subset_iff, Set.setOf_subset_setOf, imp_true_iff] rw [this] - apply tendsto_measure_iUnion + apply tendsto_measure_iUnion_atTop intro m n hmn x hx exact ⟨hx.1, hx.2.trans (Nat.cast_le.2 hmn)⟩ apply le_of_tendsto_of_tendsto A tendsto_const_nhds From 747687846c71fde9eba9b42044b2b0c8fca93e6a Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Wed, 18 Sep 2024 11:42:23 +0000 Subject: [PATCH 018/170] feat(RingTheory/StandardSmooth): base change of standard smooth algebras (#16853) Shows that being standard smooth is stable under base change. This contribution was created as part of the AIM workshop "Formalizing algebraic geometry" in June 2024. Co-authored-by: Andrew Yang @erdOne Co-authored-by: Yung Tao Cheng @rontaucheng --- Mathlib/RingTheory/Presentation.lean | 8 ++- Mathlib/RingTheory/Smooth/StandardSmooth.lean | 66 ++++++++++++++++++- .../TensorProduct/MvPolynomial.lean | 9 +++ 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index 6de568a38eb2b..ec8185b2aa0e4 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -201,7 +201,7 @@ lemma localizationAway_dimension_zero : (localizationAway r (S := S)).dimension end Localization -variable {T} [CommRing T] [Algebra R T] (P : Presentation R S) +variable (T) [CommRing T] [Algebra R T] (P : Presentation R S) private lemma span_range_relation_eq_ker_baseChange : Ideal.span (Set.range fun i ↦ (MvPolynomial.map (algebraMap R T)) (P.relation i)) = @@ -260,7 +260,11 @@ def baseChange : Presentation T (T ⊗[R] S) where __ := Generators.baseChange P.toGenerators rels := P.rels relation i := MvPolynomial.map (algebraMap R T) (P.relation i) - span_range_relation_eq_ker := P.span_range_relation_eq_ker_baseChange + span_range_relation_eq_ker := P.span_range_relation_eq_ker_baseChange T + +instance baseChange_isFinite [P.IsFinite] : (P.baseChange T).IsFinite where + finite_vars := inferInstanceAs <| Finite (P.vars) + finite_rels := inferInstanceAs <| Finite (P.rels) end Construction diff --git a/Mathlib/RingTheory/Smooth/StandardSmooth.lean b/Mathlib/RingTheory/Smooth/StandardSmooth.lean index 67da17a5eccf5..d8064eb6a7e8c 100644 --- a/Mathlib/RingTheory/Smooth/StandardSmooth.lean +++ b/Mathlib/RingTheory/Smooth/StandardSmooth.lean @@ -64,8 +64,6 @@ Finally, for ring homomorphisms we define: - Show that the canonical presentation for localization away from an element is standard smooth of relative dimension 0. -- Show that the base change of a submersive presentation is submersive of equal relative - dimension. - Show that the composition of submersive presentations of relative dimensions `n` and `m` is submersive of relative dimension `n + m`. - Show that the module of Kaehler differentials of a standard smooth `R`-algebra `S` of relative @@ -192,6 +190,38 @@ lemma ofBijectiveAlgebraMap_jacobian (h : Function.Bijective (algebraMap R S)) : contradiction rw [jacobian_eq_jacobiMatrix_det, RingHom.map_det, this, Matrix.det_one] +open MvPolynomial + +section BaseChange + +variable (T) [CommRing T] [Algebra R T] (P : PreSubmersivePresentation R S) + +/-- If `P` is a pre-submersive presentation of `S` over `R` and `T` is an `R`-algebra, we +obtain a natural pre-submersive presentation of `T ⊗[R] S` over `T`. -/ +noncomputable def baseChange : PreSubmersivePresentation T (T ⊗[R] S) where + __ := P.toPresentation.baseChange T + map := P.map + map_inj := P.map_inj + relations_finite := P.relations_finite + +lemma baseChange_jacobian : (P.baseChange T).jacobian = 1 ⊗ₜ P.jacobian := by + classical + cases nonempty_fintype P.rels + letI : Fintype (P.baseChange T).rels := inferInstanceAs <| Fintype P.rels + simp_rw [jacobian_eq_jacobiMatrix_det] + have h : (baseChange T P).jacobiMatrix = + (MvPolynomial.map (algebraMap R T)).mapMatrix P.jacobiMatrix := by + ext i j : 1 + simp only [baseChange, jacobiMatrix_apply, Presentation.baseChange_relation, + RingHom.mapMatrix_apply, Matrix.map_apply] + erw [MvPolynomial.pderiv_map] + rfl + rw [h] + erw [← RingHom.map_det, aeval_map_algebraMap] + apply aeval_one_tmul + +end BaseChange + end Constructions end PreSubmersivePresentation @@ -228,6 +258,19 @@ noncomputable def ofBijectiveAlgebraMap (h : Function.Bijective (algebraMap R S) noncomputable def id : SubmersivePresentation.{t, w} R R := ofBijectiveAlgebraMap Function.bijective_id +section BaseChange + +variable (T) [CommRing T] [Algebra R T] (P : SubmersivePresentation R S) + +/-- If `P` is a submersive presentation of `S` over `R` and `T` is an `R`-algebra, we +obtain a natural submersive presentation of `T ⊗[R] S` over `T`. -/ +noncomputable def baseChange : SubmersivePresentation T (T ⊗[R] S) where + toPreSubmersivePresentation := P.toPreSubmersivePresentation.baseChange T + jacobian_isUnit := P.baseChange_jacobian T ▸ P.jacobian_isUnit.map TensorProduct.includeRight + isFinite := Presentation.baseChange_isFinite T P.toPresentation + +end BaseChange + end Constructions end SubmersivePresentation @@ -273,6 +316,25 @@ instance IsStandardSmoothOfRelativeDimension.id : IsStandardSmoothOfRelativeDimension.{t, w} 0 R R := IsStandardSmoothOfRelativeDimension.of_algebraMap_bijective Function.bijective_id +section BaseChange + +variable (T) [CommRing T] [Algebra R T] + +instance IsStandardSmooth.baseChange [IsStandardSmooth.{t, w} R S] : + IsStandardSmooth.{t, w} T (T ⊗[R] S) where + out := by + obtain ⟨⟨P⟩⟩ := ‹IsStandardSmooth R S› + exact ⟨P.baseChange T⟩ + +instance IsStandardSmoothOfRelativeDimension.baseChange + [IsStandardSmoothOfRelativeDimension.{t, w} n R S] : + IsStandardSmoothOfRelativeDimension.{t, w} n T (T ⊗[R] S) where + out := by + obtain ⟨P, hP⟩ := ‹IsStandardSmoothOfRelativeDimension n R S› + exact ⟨P.baseChange T, hP⟩ + +end BaseChange + end Algebra namespace RingHom diff --git a/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean b/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean index 10e82ca9edd87..5b8ae61882f73 100644 --- a/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean +++ b/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean @@ -229,6 +229,15 @@ lemma algebraTensorAlgEquiv_symm_monomial (m : σ →₀ ℕ) (a : A) : nth_rw 2 [← mul_one a] rw [Algebra.TensorProduct.tmul_mul_tmul] +lemma aeval_one_tmul (f : σ → S) (p : MvPolynomial σ R) : + (aeval fun x ↦ (1 ⊗ₜ[R] f x : N ⊗[R] S)) p = 1 ⊗ₜ[R] (aeval f) p := by + induction' p using MvPolynomial.induction_on with a p q hp hq p i h + · simp only [map_C, algHom_C, Algebra.TensorProduct.algebraMap_apply, + RingHomCompTriple.comp_apply] + rw [← mul_one ((algebraMap R N) a), ← Algebra.smul_def, smul_tmul, Algebra.smul_def, mul_one] + · simp [hp, hq, tmul_add] + · simp [h] + end Algebra end MvPolynomial From 211cd6b75e344a4b13c6690cfc1bd9ad2062e4e0 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:50:51 +0000 Subject: [PATCH 019/170] feat: add AlgEquiv.symm_apply_eq (#16898) --- Mathlib/Algebra/Algebra/Equiv.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index 14000d27fb73a..d19412446121d 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -348,6 +348,12 @@ theorem apply_symm_apply (e : A₁ ≃ₐ[R] A₂) : ∀ x, e (e.symm x) = x := theorem symm_apply_apply (e : A₁ ≃ₐ[R] A₂) : ∀ x, e.symm (e x) = x := e.toEquiv.symm_apply_apply +theorem symm_apply_eq (e : A₁ ≃ₐ[R] A₂) {x y} : e.symm x = y ↔ x = e y := + e.toEquiv.symm_apply_eq + +theorem eq_symm_apply (e : A₁ ≃ₐ[R] A₂) {x y} : y = e.symm x ↔ e y = x := + e.toEquiv.eq_symm_apply + @[simp] theorem comp_symm (e : A₁ ≃ₐ[R] A₂) : AlgHom.comp (e : A₁ →ₐ[R] A₂) ↑e.symm = AlgHom.id R A₂ := by ext From 45998605cb2fa22d3fd54d0468672d1475978025 Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Wed, 18 Sep 2024 12:50:52 +0000 Subject: [PATCH 020/170] feat(NumberTheory/LSeries): polish some results on ZMod L-series (#16913) Strengthen functional equation for L-series of a function mod N so it holds at s = 1 as well (in cases where s = 1 is not a pole). Also some minor stylistic cleanup / golfing. --- Mathlib/NumberTheory/LSeries/ZMod.lean | 68 +++++++++++++++++--------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/Mathlib/NumberTheory/LSeries/ZMod.lean b/Mathlib/NumberTheory/LSeries/ZMod.lean index d7727a8fcffd7..c8ae61d647c1c 100644 --- a/Mathlib/NumberTheory/LSeries/ZMod.lean +++ b/Mathlib/NumberTheory/LSeries/ZMod.lean @@ -6,9 +6,7 @@ Authors: David Loeffler import Mathlib.Analysis.Fourier.ZMod import Mathlib.Analysis.NormedSpace.Connected -import Mathlib.LinearAlgebra.Dimension.DivisionRing import Mathlib.NumberTheory.LSeries.RiemannZeta -import Mathlib.Topology.Algebra.Module.Cardinality /-! # L-series of functions on `ZMod N` @@ -34,7 +32,7 @@ for general functions; for the specific case of Dirichlet characters see `LFunction (𝓕 Φ) s`, where `𝓕` is the Fourier transform. -/ -open HurwitzZeta Complex ZMod Finset Classical Topology Filter +open HurwitzZeta Complex ZMod Finset Classical Topology Filter Set open scoped Real @@ -70,7 +68,7 @@ lemma LFunction_eq_LSeries (Φ : ZMod N → ℂ) {s : ℂ} (hs : 1 < re s) : LFunction Φ s = LSeries (Φ ·) s := by rw [LFunction, LSeries, mul_sum, Nat.sumByResidueClasses (LSeriesSummable_of_one_lt_re Φ hs) N] congr 1 with j - have : (j.val / N : ℝ) ∈ Set.Icc 0 1 := Set.mem_Icc.mpr ⟨by positivity, + have : (j.val / N : ℝ) ∈ Set.Icc 0 1 := mem_Icc.mpr ⟨by positivity, (div_le_one (Nat.cast_pos.mpr <| NeZero.pos _)).mpr <| Nat.cast_le.mpr (val_lt j).le⟩ rw [toAddCircle_apply, ← (hasSum_hurwitzZeta_of_one_lt_re this hs).tsum_eq, ← mul_assoc, ← tsum_mul_left] @@ -119,6 +117,24 @@ lemma LFunction_residue_one (Φ : ZMod N → ℂ) : exact ((continuous_neg.const_cpow (Or.inl <| NeZero.ne _)).tendsto _).mono_left nhdsWithin_le_nhds +local notation "𝕖" => stdAddChar + +/-- +The `LFunction` of the function `x ↦ e (j * x)`, where `e : ZMod N → ℂ` is the standard additive +character, agrees with `expZeta (j / N)` on `1 < re s`. Private since it is a stepping-stone to +the more general result `LFunction_stdAddChar_eq_expZeta` below. +-/ +private lemma LFunction_stdAddChar_eq_expZeta_of_one_lt_re (j : ZMod N) {s : ℂ} (hs : 1 < s.re) : + LFunction (fun k ↦ 𝕖 (j * k)) s = expZeta (ZMod.toAddCircle j) s := by + rw [toAddCircle_apply, ← (hasSum_expZeta_of_one_lt_re (j.val / N) hs).tsum_eq, + LFunction_eq_LSeries _ hs, LSeries] + congr 1 with n + rw [LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs), ofReal_div, ofReal_natCast, + ofReal_natCast, mul_assoc, div_mul_eq_mul_div, stdAddChar_apply] + have := ZMod.toCircle_intCast (N := N) (j.val * n) + conv_rhs at this => rw [Int.cast_mul, Int.cast_natCast, Int.cast_natCast, mul_div_assoc] + rw [← this, Int.cast_mul, Int.cast_natCast, Int.cast_natCast, natCast_zmod_val] + /-- The `LFunction` of the function `x ↦ e (j * x)`, where `e : ZMod N → ℂ` is the standard additive character, is `expZeta (j / N)`. @@ -127,8 +143,8 @@ Note this is not at all obvious from the definitions, and we prove it by analyti from the convergence range. -/ lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ s ≠ 1) : - LFunction (fun k ↦ stdAddChar (j * k)) s = expZeta (ZMod.toAddCircle j) s := by - let U := if j = 0 then {z : ℂ | z ≠ 1} else Set.univ -- region of analyticity of both functions + LFunction (fun k ↦ 𝕖 (j * k)) s = expZeta (ZMod.toAddCircle j) s := by + let U := if j = 0 then {z : ℂ | z ≠ 1} else univ -- region of analyticity of both functions let V := {z : ℂ | 1 < re z} -- convergence region have hUo : IsOpen U := by by_cases h : j = 0 @@ -136,7 +152,7 @@ lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ · simp only [h, ↓reduceIte, isOpen_univ, U] let f := LFunction (fun k ↦ stdAddChar (j * k)) let g := expZeta (toAddCircle j) - have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [Set.mem_ite_univ_right, U]; tauto + have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [mem_ite_univ_right, U]; tauto -- hypotheses for uniqueness of analytic continuation have hf : AnalyticOn ℂ f U := by refine DifferentiableOn.analyticOn (fun u hu ↦ ?_) hUo @@ -158,41 +174,47 @@ lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ -- apply uniqueness result refine hf.eqOn_of_preconnected_of_eventuallyEq hg hUc hUmem ?_ hUmem' -- now remains to prove equality on `1 < re s` - filter_upwards [hV] with z hz - dsimp only [f, g] - rw [toAddCircle_apply, ← (hasSum_expZeta_of_one_lt_re (j.val / N) hz).tsum_eq, - LFunction_eq_LSeries _ hz, LSeries] - congr 1 with n - rw [LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hz), ofReal_div, ofReal_natCast, - ofReal_natCast, mul_assoc, div_mul_eq_mul_div, stdAddChar_apply] - have := ZMod.toCircle_intCast (N := N) (j.val * n) - conv_rhs at this => rw [Int.cast_mul, Int.cast_natCast, Int.cast_natCast, mul_div_assoc] - rw [← this, Int.cast_mul, Int.cast_natCast, Int.cast_natCast, natCast_zmod_val] + filter_upwards [hV] with z using LFunction_stdAddChar_eq_expZeta_of_one_lt_re _ /-- Explicit formula for the L-function of `𝓕 Φ`, where `𝓕` is the discrete Fourier transform. -/ -lemma LFunction_dft (Φ : ZMod N → ℂ) {s : ℂ} (hs : s ≠ 1) : +lemma LFunction_dft (Φ : ZMod N → ℂ) {s : ℂ} (hs : Φ 0 = 0 ∨ s ≠ 1) : LFunction (𝓕 Φ) s = ∑ j : ZMod N, Φ j * expZeta (toAddCircle (-j)) s := by - simp only [← LFunction_stdAddChar_eq_expZeta _ _ (Or.inr hs), LFunction, mul_sum] - rw [sum_comm, dft_def] + have (j : ZMod N) : Φ j * LFunction (fun k ↦ 𝕖 (-j * k)) s = + Φ j * expZeta (toAddCircle (-j)) s := by + by_cases h : -j ≠ 0 ∨ s ≠ 1 + · rw [LFunction_stdAddChar_eq_expZeta _ _ h] + · simp only [neg_ne_zero, not_or, not_not] at h + rw [h.1, show Φ 0 = 0 by tauto, zero_mul, zero_mul] + simp only [LFunction, ← this, mul_sum] + rw [dft_def, sum_comm] simp only [sum_mul, mul_sum, Circle.smul_def, smul_eq_mul, stdAddChar_apply, ← mul_assoc] congr 1 with j congr 1 with k rw [mul_assoc (Φ _), mul_comm (Φ _), neg_mul] /-- Functional equation for `ZMod` L-functions, in terms of discrete Fourier transform. -/ -theorem LFunction_one_sub (Φ : ZMod N → ℂ) {s : ℂ} (hs : ∀ (n : ℕ), s ≠ -↑n) (hs' : s ≠ 1) : +theorem LFunction_one_sub (Φ : ZMod N → ℂ) {s : ℂ} + (hs : ∀ (n : ℕ), s ≠ -n) (hs' : Φ 0 = 0 ∨ s ≠ 1) : LFunction Φ (1 - s) = N ^ (s - 1) * (2 * π) ^ (-s) * Gamma s * (cexp (π * I * s / 2) * LFunction (𝓕 Φ) s + cexp (-π * I * s / 2) * LFunction (𝓕 fun x ↦ Φ (-x)) s) := by rw [LFunction] - simp only [hurwitzZeta_one_sub _ hs (Or.inr hs'), mul_assoc _ _ (Gamma s)] + have (j : ZMod N) : Φ j * hurwitzZeta (toAddCircle j) (1 - s) = Φ j * + ((2 * π) ^ (-s) * Gamma s * (cexp (-π * I * s / 2) * + expZeta (toAddCircle j) s + cexp (π * I * s / 2) * expZeta (-toAddCircle j) s)) := by + rcases eq_or_ne j 0 with rfl | hj + · rcases hs' with hΦ | hs' + · simp only [hΦ, zero_mul] + · rw [hurwitzZeta_one_sub _ hs (Or.inr hs')] + · rw [hurwitzZeta_one_sub _ hs (Or.inl <| toAddCircle_eq_zero.not.mpr hj)] + simp only [this, mul_assoc _ _ (Gamma s)] -- get rid of Gamma terms and power of N generalize (2 * π) ^ (-s) * Gamma s = C simp_rw [← mul_assoc, mul_comm _ C, mul_assoc, ← mul_sum, ← mul_assoc, mul_comm _ C, mul_assoc, neg_sub] congr 2 -- now gather sum terms - rw [LFunction_dft _ hs', LFunction_dft _ hs'] + rw [LFunction_dft _ hs', LFunction_dft _ (hs'.imp_left <| by simp only [neg_zero, imp_self])] conv_rhs => enter [2, 2]; rw [← (Equiv.neg _).sum_comp _ _ (by simp), Equiv.neg_apply] simp_rw [neg_neg, mul_sum, ← sum_add_distrib, ← mul_assoc, mul_comm _ (Φ _), mul_assoc, ← mul_add, map_neg, add_comm] From ca613b5c52e6c064681fc5da427208e8fa9fbb52 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Wed, 18 Sep 2024 15:38:02 +0000 Subject: [PATCH 021/170] doc(Algebra/CharP/CharAndCard): correct documentation of not_isUnit_prime_of_dvd_card (#16924) --- Mathlib/Algebra/CharP/CharAndCard.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/CharP/CharAndCard.lean b/Mathlib/Algebra/CharP/CharAndCard.lean index bbd284531afbf..75671724d2c94 100644 --- a/Mathlib/Algebra/CharP/CharAndCard.lean +++ b/Mathlib/Algebra/CharP/CharAndCard.lean @@ -70,8 +70,8 @@ theorem prime_dvd_char_iff_dvd_card {R : Type*} [CommRing R] [Fintype R] (p : rw [mul_zero, ← mul_assoc, hu, one_mul] at hr₁ exact mt AddMonoid.addOrderOf_eq_one_iff.mpr (ne_of_eq_of_ne hr (Nat.Prime.ne_one Fact.out)) hr₁ -/-- A prime that does not divide the cardinality of a finite commutative ring `R` -is a unit in `R`. -/ +/-- A prime that divides the cardinality of a finite commutative ring `R` +isn't a unit in `R`. -/ theorem not_isUnit_prime_of_dvd_card {R : Type*} [CommRing R] [Fintype R] (p : ℕ) [Fact p.Prime] (hp : p ∣ Fintype.card R) : ¬IsUnit (p : R) := mt (isUnit_iff_not_dvd_char R p).mp From 389689778ce64e9f15519110b947f56cd75f25a4 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:41:55 +0000 Subject: [PATCH 022/170] feat: generalize projective module results to semirings (#16741) --- Mathlib/Algebra/Module/Projective.lean | 29 +++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Mathlib/Algebra/Module/Projective.lean b/Mathlib/Algebra/Module/Projective.lean index ea72b33e221e7..b4387f01f63c9 100644 --- a/Mathlib/Algebra/Module/Projective.lean +++ b/Mathlib/Algebra/Module/Projective.lean @@ -140,12 +140,6 @@ instance [h : ∀ i : ι, Projective R (A i)] : Projective R (Π₀ i, A i) := ext i x j simp only [comp_apply, id_apply, DFinsupp.lsingle_apply, DFinsupp.coprodMap_apply_single, hg] -end Semiring - -section Ring - -variable {R : Type u} [Ring R] {P : Type v} [AddCommGroup P] [Module R P] - /-- Free modules are projective. -/ theorem Projective.of_basis {ι : Type*} (b : Basis ι R P) : Projective R P := by -- need P →ₗ (P →₀ R) for definition of projective. @@ -159,9 +153,6 @@ theorem Projective.of_basis {ι : Type*} (b : Basis ι R P) : Projective R P := instance (priority := 100) Projective.of_free [Module.Free R P] : Module.Projective R P := .of_basis <| Module.Free.chooseBasis R P -variable {R₀ M N} [CommRing R₀] [Algebra R₀ R] [AddCommGroup M] [Module R₀ M] [Module R M] -variable [IsScalarTower R₀ R M] [AddCommGroup N] [Module R₀ N] - theorem Projective.of_split [Module.Projective R M] (i : P →ₗ[R] M) (s : M →ₗ[R] P) (H : s.comp i = LinearMap.id) : Module.Projective R P := by obtain ⟨g, hg⟩ := projective_lifting_property (Finsupp.linearCombination R id) s @@ -174,6 +165,20 @@ theorem Projective.of_equiv [Module.Projective R M] (e : M ≃ₗ[R] P) : Module.Projective R P := Projective.of_split e.symm e.toLinearMap (by ext; simp) +/-- A quotient of a projective module is projective iff it is a direct summand. -/ +theorem Projective.iff_split_of_projective [Module.Projective R M] (s : M →ₗ[R] P) + (hs : Function.Surjective s) : + Module.Projective R P ↔ ∃ i, s ∘ₗ i = LinearMap.id := + ⟨fun _ ↦ projective_lifting_property _ _ hs, fun ⟨i, H⟩ ↦ Projective.of_split i s H⟩ + +end Semiring + +section Ring + +variable {R : Type u} [Ring R] {P : Type v} [AddCommMonoid P] [Module R P] +variable {R₀ M N} [CommRing R₀] [Algebra R₀ R] [AddCommGroup M] [Module R₀ M] [Module R M] +variable [IsScalarTower R₀ R M] [AddCommGroup N] [Module R₀ N] + /-- A module is projective iff it is the direct summand of a free module. -/ theorem Projective.iff_split : Module.Projective R P ↔ ∃ (M : Type max u v) (_ : AddCommGroup M) (_ : Module R M) (_ : Module.Free R M) @@ -181,12 +186,6 @@ theorem Projective.iff_split : Module.Projective R P ↔ ⟨fun ⟨i, hi⟩ ↦ ⟨P →₀ R, _, _, inferInstance, i, Finsupp.linearCombination R id, LinearMap.ext hi⟩, fun ⟨_, _, _, _, i, s, H⟩ ↦ Projective.of_split i s H⟩ -/-- A quotient of a projective module is projective iff it is a direct summand. -/ -theorem Projective.iff_split_of_projective [Module.Projective R M] (s : M →ₗ[R] P) - (hs : Function.Surjective s) : - Module.Projective R P ↔ ∃ i, s ∘ₗ i = LinearMap.id := - ⟨fun _ ↦ projective_lifting_property _ _ hs, fun ⟨i, H⟩ ↦ Projective.of_split i s H⟩ - set_option maxSynthPendingDepth 2 in open TensorProduct in instance Projective.tensorProduct [hM : Module.Projective R M] [hN : Module.Projective R₀ N] : From a5f29991949bf657a12a5caf1b3618072b8990a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Wed, 18 Sep 2024 16:52:48 +0000 Subject: [PATCH 023/170] chore(SetTheory/Ordinal/NaturalOps): fix argument implicitness (#16900) --- Mathlib/SetTheory/Ordinal/NaturalOps.lean | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mathlib/SetTheory/Ordinal/NaturalOps.lean b/Mathlib/SetTheory/Ordinal/NaturalOps.lean index 8e28f13a7e945..b901e17cfa608 100644 --- a/Mathlib/SetTheory/Ordinal/NaturalOps.lean +++ b/Mathlib/SetTheory/Ordinal/NaturalOps.lean @@ -106,19 +106,19 @@ theorem toOrdinal_one : toOrdinal 1 = 1 := rfl @[simp] -theorem toOrdinal_eq_zero (a) : toOrdinal a = 0 ↔ a = 0 := +theorem toOrdinal_eq_zero {a} : toOrdinal a = 0 ↔ a = 0 := Iff.rfl @[simp] -theorem toOrdinal_eq_one (a) : toOrdinal a = 1 ↔ a = 1 := +theorem toOrdinal_eq_one {a} : toOrdinal a = 1 ↔ a = 1 := Iff.rfl @[simp] -theorem toOrdinal_max {a b : NatOrdinal} : toOrdinal (max a b) = max (toOrdinal a) (toOrdinal b) := +theorem toOrdinal_max (a b : NatOrdinal) : toOrdinal (max a b) = max (toOrdinal a) (toOrdinal b) := rfl @[simp] -theorem toOrdinal_min {a b : NatOrdinal} : toOrdinal (min a b) = min (toOrdinal a) (toOrdinal b) := +theorem toOrdinal_min (a b : NatOrdinal) : toOrdinal (min a b) = min (toOrdinal a) (toOrdinal b) := rfl theorem succ_def (a : NatOrdinal) : succ a = toNatOrdinal (toOrdinal a + 1) := From 95af9be74f8b9d98505d9900fe8f563a89e5e667 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 18 Sep 2024 17:04:01 +0000 Subject: [PATCH 024/170] feat: Composition.blocksFun_le (#16814) --- .../Algebra/Order/BigOperators/Group/List.lean | 16 +++++++++++++++- .../Combinatorics/Enumerative/Composition.lean | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Order/BigOperators/Group/List.lean b/Mathlib/Algebra/Order/BigOperators/Group/List.lean index 7872ed429ca63..3d5a671d2a7f8 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/List.lean @@ -143,7 +143,8 @@ lemma one_lt_prod_of_one_lt [OrderedCommMonoid M] : · exact hl₁.2.1 · exact hl₁.2.2 _ ‹_› -@[to_additive] +/-- See also `List.le_prod_of_mem`. -/ +@[to_additive "See also `List.le_sum_of_mem`."] lemma single_le_prod [OrderedCommMonoid M] {l : List M} (hl₁ : ∀ x ∈ l, (1 : M) ≤ x) : ∀ x ∈ l, x ≤ l.prod := by induction l @@ -174,5 +175,18 @@ variable [CanonicallyOrderedCommMonoid M] {l : List M} exact le_self_mul · simp [take_of_length_le h, take_of_length_le (le_trans h (Nat.le_succ _))] +/-- See also `List.single_le_prod`. -/ +@[to_additive "See also `List.single_le_sum`."] +theorem le_prod_of_mem {xs : List M} {x : M} (h₁ : x ∈ xs) : x ≤ xs.prod := by + induction xs with + | nil => simp at h₁ + | cons y ys ih => + simp only [mem_cons] at h₁ + rcases h₁ with (rfl | h₁) + · simp + · specialize ih h₁ + simp only [List.prod_cons] + exact le_mul_left ih + end CanonicallyOrderedCommMonoid end List diff --git a/Mathlib/Combinatorics/Enumerative/Composition.lean b/Mathlib/Combinatorics/Enumerative/Composition.lean index a7e73aefb67e9..917e4a7e41dbc 100644 --- a/Mathlib/Combinatorics/Enumerative/Composition.lean +++ b/Mathlib/Combinatorics/Enumerative/Composition.lean @@ -168,6 +168,12 @@ theorem blocks_pos' (i : ℕ) (h : i < c.length) : 0 < c.blocks[i] := theorem one_le_blocksFun (i : Fin c.length) : 1 ≤ c.blocksFun i := c.one_le_blocks (c.blocksFun_mem_blocks i) +theorem blocksFun_le {n} (c : Composition n) (i : Fin c.length) : + c.blocksFun i ≤ n := by + have := c.blocks_sum + have := List.le_sum_of_mem (c.blocksFun_mem_blocks i) + simp_all + theorem length_le : c.length ≤ n := by conv_rhs => rw [← c.blocks_sum] exact length_le_sum_of_one_le _ fun i hi => c.one_le_blocks hi From 51a9d75766204ed306daf9b12f34105a477e2a1b Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 18 Sep 2024 17:46:03 +0000 Subject: [PATCH 025/170] chore(SuccPred/Basic): minor golf (#16905) --- Mathlib/Order/SuccPred/Basic.lean | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Mathlib/Order/SuccPred/Basic.lean b/Mathlib/Order/SuccPred/Basic.lean index 32371ab7995e0..d8d173cca893a 100644 --- a/Mathlib/Order/SuccPred/Basic.lean +++ b/Mathlib/Order/SuccPred/Basic.lean @@ -223,15 +223,13 @@ lemma le_succ_of_wcovBy (h : a ⩿ b) : b ≤ succ a := by alias _root_.WCovBy.le_succ := le_succ_of_wcovBy -theorem le_succ_iterate (k : ℕ) (x : α) : x ≤ succ^[k] x := by - conv_lhs => rw [(by simp only [Function.iterate_id, id] : x = id^[k] x)] - exact Monotone.le_iterate_of_le succ_mono le_succ k x +theorem le_succ_iterate (k : ℕ) (x : α) : x ≤ succ^[k] x := + id_le_iterate_of_id_le le_succ _ _ theorem isMax_iterate_succ_of_eq_of_lt {n m : ℕ} (h_eq : succ^[n] a = succ^[m] a) (h_lt : n < m) : IsMax (succ^[n] a) := by refine max_of_succ_le (le_trans ?_ h_eq.symm.le) - have : succ (succ^[n] a) = succ^[n + 1] a := by rw [Function.iterate_succ', comp] - rw [this] + rw [← iterate_succ_apply' succ] have h_le : n + 1 ≤ m := Nat.succ_le_of_lt h_lt exact Monotone.monotone_iterate_of_le_map succ_mono (le_succ a) h_le From ee33a2f79467b78b5d8b372f5365ee5671e28e90 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:30:59 +0000 Subject: [PATCH 026/170] chore: tidy various files (#16718) --- Archive/Imo/Imo1987Q1.lean | 11 +--- Mathlib/Algebra/Algebra/Operations.lean | 2 +- Mathlib/Algebra/BigOperators/Finsupp.lean | 3 +- Mathlib/Algebra/BigOperators/Ring.lean | 2 +- Mathlib/Algebra/Group/Subgroup/Basic.lean | 2 +- .../Algebra/Group/Subgroup/MulOpposite.lean | 2 +- .../Algebra/Group/Submonoid/MulOpposite.lean | 2 +- Mathlib/Algebra/Lie/EngelSubalgebra.lean | 5 +- Mathlib/Algebra/Lie/OfAssociative.lean | 2 +- Mathlib/Algebra/Lie/Solvable.lean | 2 +- Mathlib/Algebra/Order/Star/Conjneg.lean | 2 +- Mathlib/Algebra/Ring/Subring/MulOpposite.lean | 2 +- .../Algebra/Ring/Subsemiring/MulOpposite.lean | 2 +- .../SpecialFunctions/Log/ENNRealLog.lean | 66 ++++++++----------- Mathlib/Combinatorics/SimpleGraph/Walk.lean | 27 ++++---- Mathlib/Data/ENat/Basic.lean | 11 +--- .../MeasureTheory/Measure/MeasureSpace.lean | 2 +- Mathlib/Order/RelSeries.lean | 2 +- Mathlib/Order/ScottContinuity.lean | 4 +- .../Order/SuccPred/LinearLocallyFinite.lean | 15 +++-- Mathlib/Probability/Kernel/Composition.lean | 14 ++-- .../RingTheory/Valuation/ValExtension.lean | 6 +- .../Algebra/Module/Alternating/Topology.lean | 5 +- .../Topology/OmegaCompletePartialOrder.lean | 7 +- Mathlib/Topology/Order/Monotone.lean | 18 ++--- 25 files changed, 95 insertions(+), 121 deletions(-) diff --git a/Archive/Imo/Imo1987Q1.lean b/Archive/Imo/Imo1987Q1.lean index 36d3caf4a519e..d10995da9a7a4 100644 --- a/Archive/Imo/Imo1987Q1.lean +++ b/Archive/Imo/Imo1987Q1.lean @@ -47,14 +47,9 @@ def fixedPointsEquiv : { σx : α × Perm α // σx.2 σx.1 = σx.1 } ≃ Σ x : theorem card_fixed_points : card { σx : α × Perm α // σx.2 σx.1 = σx.1 } = card α * (card α - 1)! := by simp only [card_congr (fixedPointsEquiv α), card_sigma, card_perm] - conv_lhs => - congr - next => skip - intro - rw [card_ofFinset (s := Finset.filter (· ∈ _) Finset.univ)] - simp only [Set.mem_compl_iff, Set.mem_singleton_iff, Finset.filter_not, Finset.filter_eq', - Finset.mem_univ, ↓reduceIte, Finset.subset_univ, Finset.card_sdiff, Finset.card_univ, - Finset.card_singleton, sum_const, smul_eq_mul] + have (x) : ({x}ᶜ : Set α) = Finset.filter (· ≠ x) Finset.univ := by + ext; simp + simp [this] /-- Given `α : Type*` and `k : ℕ`, `fiber α k` is the set of permutations of `α` with exactly `k` fixed points. -/ diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index 46b892900e21b..15f0ec29f05ab 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -364,7 +364,7 @@ theorem mul_smul_mul_eq_smul_mul_smul (x y : R) : (x * y) • (M * N) = (x • M · rw [smul_add] exact Submodule.add_mem _ hn hm · rintro _ ⟨m, hm, rfl⟩ _ ⟨n, hn, rfl⟩ - erw [smul_mul_smul_comm x m y n] + simp_rw [DistribMulAction.toLinearMap_apply, smul_mul_smul_comm] exact smul_mem_pointwise_smul _ _ _ (mul_mem_mul hm hn) /-- Sub-R-modules of an R-algebra form an idempotent semiring. -/ diff --git a/Mathlib/Algebra/BigOperators/Finsupp.lean b/Mathlib/Algebra/BigOperators/Finsupp.lean index 25a6ab9d28063..35f43a5d0baa1 100644 --- a/Mathlib/Algebra/BigOperators/Finsupp.lean +++ b/Mathlib/Algebra/BigOperators/Finsupp.lean @@ -346,8 +346,7 @@ def liftAddHom [AddZeroClass M] [AddCommMonoid N] : (α → M →+ N) ≃+ ((α ext simp [singleAddHom] right_inv F := by - -- Porting note: This was `ext` and used the wrong lemma - apply Finsupp.addHom_ext' + ext simp [singleAddHom, AddMonoidHom.comp, Function.comp_def] map_add' F G := by ext x diff --git a/Mathlib/Algebra/BigOperators/Ring.lean b/Mathlib/Algebra/BigOperators/Ring.lean index 0cf28cc97f8a8..8ffa27de019be 100644 --- a/Mathlib/Algebra/BigOperators/Ring.lean +++ b/Mathlib/Algebra/BigOperators/Ring.lean @@ -110,7 +110,7 @@ lemma prod_sum (s : Finset ι) (t : ∀ i, Finset (κ i)) (f : ∀ i, κ i → ∏ a ∈ s, ∑ b ∈ t a, f a b = ∑ p ∈ s.pi t, ∏ x ∈ s.attach, f x.1 (p x.1 x.2) := by classical induction s using Finset.induction with - | empty => rw [pi_empty, sum_singleton]; rfl + | empty => simp | insert ha ih => rename_i a s have h₁ : ∀ x ∈ t a, ∀ y ∈ t a, x ≠ y → diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index ba423e5b8a907..7881c95bcec47 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -583,7 +583,7 @@ theorem coe_pow (x : H) (n : ℕ) : ((x ^ n : H) : G) = (x : G) ^ n := theorem coe_zpow (x : H) (n : ℤ) : ((x ^ n : H) : G) = (x : G) ^ n := rfl -@[to_additive (attr := simp)] -- This can be proved by `Submonoid.mk_eq_one` +@[to_additive (attr := simp)] theorem mk_eq_one {g : G} {h} : (⟨g, h⟩ : H) = 1 ↔ g = 1 := Submonoid.mk_eq_one .. /-- A subgroup of a group inherits a group structure. -/ diff --git a/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean b/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean index df6846f493e89..296424c376749 100644 --- a/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean +++ b/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean @@ -181,7 +181,7 @@ theorem op_closure (s : Set G) : (closure s).op = closure (MulOpposite.unop ⁻ @[to_additive] theorem unop_closure (s : Set Gᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by rw [← op_inj, op_unop, op_closure] - rfl + simp_rw [Set.preimage_preimage, MulOpposite.op_unop, Set.preimage_id'] /-- Bijection between a subgroup `H` and its opposite. -/ @[to_additive (attr := simps!) "Bijection between an additive subgroup `H` and its opposite."] diff --git a/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean b/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean index ce69dc1d1759d..9157b526b564c 100644 --- a/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean +++ b/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean @@ -164,7 +164,7 @@ theorem op_closure (s : Set M) : (closure s).op = closure (MulOpposite.unop ⁻ @[to_additive] theorem unop_closure (s : Set Mᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by rw [← op_inj, op_unop, op_closure] - rfl + simp_rw [Set.preimage_preimage, MulOpposite.op_unop, Set.preimage_id'] /-- Bijection between a submonoid `H` and its opposite. -/ @[to_additive (attr := simps!) "Bijection between an additive submonoid `H` and its opposite."] diff --git a/Mathlib/Algebra/Lie/EngelSubalgebra.lean b/Mathlib/Algebra/Lie/EngelSubalgebra.lean index 031da676554e7..3a6654de89875 100644 --- a/Mathlib/Algebra/Lie/EngelSubalgebra.lean +++ b/Mathlib/Algebra/Lie/EngelSubalgebra.lean @@ -133,8 +133,9 @@ lemma normalizer_eq_self_of_engel_le [IsArtinian R L] clear hk; revert hy generalize k+1 = k induction k generalizing y with - | zero => cases y; intro hy; simp only [pow_zero, LinearMap.one_apply]; exact - (AddSubmonoid.mk_eq_zero N.toAddSubmonoid).mp hy + | zero => + cases y; intro hy; simp only [pow_zero, LinearMap.one_apply] + exact (AddSubmonoid.mk_eq_zero N.toAddSubmonoid).mp hy | succ k ih => simp only [pow_succ, LinearMap.mem_ker, LinearMap.mul_apply] at ih ⊢; apply ih · rw [← Submodule.map_le_iff_le_comap] apply le_sup_of_le_right diff --git a/Mathlib/Algebra/Lie/OfAssociative.lean b/Mathlib/Algebra/Lie/OfAssociative.lean index fbf65f369ddf6..5b5c5283887a5 100644 --- a/Mathlib/Algebra/Lie/OfAssociative.lean +++ b/Mathlib/Algebra/Lie/OfAssociative.lean @@ -300,7 +300,7 @@ theorem toEnd_comp_subtype_mem (m : M) (hm : m ∈ (N : Submodule R M)) : @[simp] theorem toEnd_restrict_eq_toEnd (h := N.toEnd_comp_subtype_mem x) : (toEnd R L M x).restrict h = toEnd R L N x := by - ext; simp only [LinearMap.restrict_apply, toEnd_apply_apply]; rfl + ext; simp only [LinearMap.restrict_apply, toEnd_apply_apply, ← coe_bracket] lemma mapsTo_pow_toEnd_sub_algebraMap {φ : R} {k : ℕ} {x : L} : MapsTo ((toEnd R L M x - algebraMap R (Module.End R M) φ) ^ k) N N := by diff --git a/Mathlib/Algebra/Lie/Solvable.lean b/Mathlib/Algebra/Lie/Solvable.lean index 6e125fbedd552..8633e9ede390b 100644 --- a/Mathlib/Algebra/Lie/Solvable.lean +++ b/Mathlib/Algebra/Lie/Solvable.lean @@ -198,7 +198,7 @@ namespace LieAlgebra class IsSolvable : Prop where solvable : ∃ k, derivedSeries R L k = ⊥ -instance isSolvableBot : IsSolvable R ((⊥ : LieIdeal R L)) := +instance isSolvableBot : IsSolvable R (⊥ : LieIdeal R L) := ⟨⟨0, Subsingleton.elim _ ⊥⟩⟩ instance isSolvableAdd {I J : LieIdeal R L} [hI : IsSolvable R I] [hJ : IsSolvable R J] : diff --git a/Mathlib/Algebra/Order/Star/Conjneg.lean b/Mathlib/Algebra/Order/Star/Conjneg.lean index 091da606b1727..e3a93e2c3e500 100644 --- a/Mathlib/Algebra/Order/Star/Conjneg.lean +++ b/Mathlib/Algebra/Order/Star/Conjneg.lean @@ -13,7 +13,7 @@ import Mathlib.Algebra.Star.Conjneg open scoped ComplexConjugate -variable {ι G R : Type*} [AddGroup G] +variable {G R : Type*} [AddGroup G] section OrderedCommSemiring variable [OrderedCommSemiring R] [StarRing R] [StarOrderedRing R] {f : G → R} diff --git a/Mathlib/Algebra/Ring/Subring/MulOpposite.lean b/Mathlib/Algebra/Ring/Subring/MulOpposite.lean index 77448007af326..3234c63eecfab 100644 --- a/Mathlib/Algebra/Ring/Subring/MulOpposite.lean +++ b/Mathlib/Algebra/Ring/Subring/MulOpposite.lean @@ -141,7 +141,7 @@ theorem op_closure (s : Set R) : (closure s).op = closure (MulOpposite.unop ⁻ theorem unop_closure (s : Set Rᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by rw [← op_inj, op_unop, op_closure] - rfl + simp_rw [Set.preimage_preimage, MulOpposite.op_unop, Set.preimage_id'] /-- Bijection between a subring `S` and its opposite. -/ @[simps!] diff --git a/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean b/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean index ca90d5e223c98..f709792084761 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean @@ -147,7 +147,7 @@ theorem op_closure (s : Set R) : (closure s).op = closure (MulOpposite.unop ⁻ theorem unop_closure (s : Set Rᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by rw [← op_inj, op_unop, op_closure] - rfl + simp_rw [Set.preimage_preimage, MulOpposite.op_unop, Set.preimage_id'] /-- Bijection between a subsemiring `S` and its opposite. -/ @[simps!] diff --git a/Mathlib/Analysis/SpecialFunctions/Log/ENNRealLog.lean b/Mathlib/Analysis/SpecialFunctions/Log/ENNRealLog.lean index 0028886a44787..68243cfc4a5e8 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/ENNRealLog.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/ENNRealLog.lean @@ -51,24 +51,20 @@ noncomputable def log (x : ℝ≥0∞) : EReal := @[simp] lemma log_ofReal (x : ℝ) : log (ENNReal.ofReal x) = if x ≤ 0 then ⊥ else ↑(Real.log x) := by simp only [log, ENNReal.none_eq_top, ENNReal.ofReal_ne_top, IsEmpty.forall_iff, - ENNReal.ofReal_eq_zero, EReal.coe_ennreal_ofReal] + ENNReal.ofReal_eq_zero, EReal.coe_ennreal_ofReal, if_false] split_ifs with h_nonpos · rfl - · trivial - · rw [ENNReal.toReal_ofReal] - exact (not_le.mp h_nonpos).le + · rw [ENNReal.toReal_ofReal (not_le.mp h_nonpos).le] lemma log_ofReal_of_pos {x : ℝ} (hx : 0 < x) : log (ENNReal.ofReal x) = Real.log x := by - rw [log_ofReal, if_neg] - exact not_le.mpr hx + rw [log_ofReal, if_neg hx.not_le] theorem log_pos_real {x : ℝ≥0∞} (h : x ≠ 0) (h' : x ≠ ⊤) : log x = Real.log (ENNReal.toReal x) := by simp [log, h, h'] theorem log_pos_real' {x : ℝ≥0∞} (h : 0 < x.toReal) : log x = Real.log (ENNReal.toReal x) := by - simp [log, Ne.symm (ne_of_lt (ENNReal.toReal_pos_iff.1 h).1), - ne_of_lt (ENNReal.toReal_pos_iff.1 h).2] + simp [log, (ENNReal.toReal_pos_iff.1 h).1.ne', (ENNReal.toReal_pos_iff.1 h).2.ne] theorem log_of_nnreal {x : ℝ≥0} (h : x ≠ 0) : log (x : ℝ≥0∞) = Real.log x := by simp [log, h] @@ -85,19 +81,19 @@ theorem log_strictMono : StrictMono log := by · rcases ENNReal.trichotomy y with (rfl | rfl | y_real) · exfalso; exact lt_irrefl 0 h · simp - · simp [Ne.symm (ne_of_lt (ENNReal.toReal_pos_iff.1 y_real).1), - ne_of_lt (ENNReal.toReal_pos_iff.1 y_real).2, EReal.bot_lt_coe] - · exfalso; exact (ne_top_of_lt h) (Eq.refl ⊤) - · simp only [Ne.symm (ne_of_lt (ENNReal.toReal_pos_iff.1 x_real).1), - ne_of_lt (ENNReal.toReal_pos_iff.1 x_real).2] + · simp [(ENNReal.toReal_pos_iff.1 y_real).1.ne', + (ENNReal.toReal_pos_iff.1 y_real).2.ne, EReal.bot_lt_coe] + · exfalso; exact not_top_lt h + · simp only [(ENNReal.toReal_pos_iff.1 x_real).1.ne', + (ENNReal.toReal_pos_iff.1 x_real).2.ne, if_false] rcases ENNReal.trichotomy y with (rfl | rfl | y_real) · exfalso; rw [← ENNReal.bot_eq_zero] at h; exact not_lt_bot h · simp - · simp only [Ne.symm (ne_of_lt (ENNReal.toReal_pos_iff.1 y_real).1), ↓reduceIte, - ne_of_lt (ENNReal.toReal_pos_iff.1 y_real).2, EReal.coe_lt_coe_iff] + · simp only [(ENNReal.toReal_pos_iff.1 y_real).1.ne', ↓reduceIte, + (ENNReal.toReal_pos_iff.1 y_real).2.ne, EReal.coe_lt_coe_iff] apply Real.log_lt_log x_real - exact (ENNReal.toReal_lt_toReal (ne_of_lt (ENNReal.toReal_pos_iff.1 x_real).2) - (ne_of_lt (ENNReal.toReal_pos_iff.1 y_real).2)).2 h + exact (ENNReal.toReal_lt_toReal (ENNReal.toReal_pos_iff.1 x_real).2.ne + (ENNReal.toReal_pos_iff.1 y_real).2.ne).2 h theorem log_monotone : Monotone log := log_strictMono.monotone @@ -112,14 +108,14 @@ theorem log_surjective : Function.Surjective log := by use ENNReal.ofReal (Real.exp y.toReal) have exp_y_pos := not_le_of_lt (Real.exp_pos y.toReal) simp only [log, ofReal_eq_zero, exp_y_pos, ↓reduceIte, ofReal_ne_top, - ENNReal.toReal_ofReal (le_of_lt (Real.exp_pos y.toReal)), Real.log_exp y.toReal] - exact EReal.coe_toReal (ne_of_lt y_ntop) (Ne.symm (ne_of_lt y_nbot)) + ENNReal.toReal_ofReal (Real.exp_pos y.toReal).le, Real.log_exp y.toReal] + exact EReal.coe_toReal y_ntop.ne y_nbot.ne' theorem log_bijective : Function.Bijective log := ⟨log_injective, log_surjective⟩ @[simp] theorem log_eq_iff {x y : ℝ≥0∞} : log x = log y ↔ x = y := - Iff.intro (@log_injective x y) (fun h ↦ by rw [h]) + log_injective.eq_iff @[simp] theorem log_eq_bot_iff {x : ℝ≥0∞} : log x = ⊥ ↔ x = 0 := log_zero ▸ @log_eq_iff x 0 @@ -158,13 +154,13 @@ theorem log_mul_add {x y : ℝ≥0∞} : log (x * y) = log x + log y := by · simp · rw [log_pos_real' y_real, ENNReal.top_mul', EReal.top_add_coe, log_eq_top_iff] simp only [ite_eq_right_iff, zero_ne_top, imp_false] - exact Ne.symm (ne_of_lt (ENNReal.toReal_pos_iff.1 y_real).1) + exact (ENNReal.toReal_pos_iff.1 y_real).1.ne' · rw [log_pos_real' x_real] rcases ENNReal.trichotomy y with (rfl | rfl | y_real) · simp - · simp [Ne.symm (ne_of_lt (ENNReal.toReal_pos_iff.1 x_real).1)] + · simp [(ENNReal.toReal_pos_iff.1 x_real).1.ne'] · rw_mod_cast [log_pos_real', log_pos_real' y_real, ENNReal.toReal_mul] - · exact Real.log_mul (Ne.symm (ne_of_lt x_real)) (Ne.symm (ne_of_lt y_real)) + · exact Real.log_mul x_real.ne' y_real.ne' rw [toReal_mul] positivity @@ -172,24 +168,20 @@ theorem log_pow {x : ℝ≥0∞} {n : ℕ} : log (x ^ n) = n * log x := by cases' Nat.eq_zero_or_pos n with n_zero n_pos · simp [n_zero, pow_zero x] rcases ENNReal.trichotomy x with (rfl | rfl | x_real) - · rw [zero_pow (Ne.symm (ne_of_lt n_pos)), log_zero, EReal.mul_bot_of_pos (Nat.cast_pos'.2 n_pos)] + · rw [zero_pow n_pos.ne', log_zero, EReal.mul_bot_of_pos (Nat.cast_pos'.2 n_pos)] · rw [ENNReal.top_pow n_pos, log_top, EReal.mul_top_of_pos (Nat.cast_pos'.2 n_pos)] · replace x_real := ENNReal.toReal_pos_iff.1 x_real - have x_ne_zero := Ne.symm (LT.lt.ne x_real.1) - have x_ne_top := LT.lt.ne x_real.2 - simp only [log, pow_eq_zero_iff', x_ne_zero, false_and, ↓reduceIte, pow_eq_top_iff, x_ne_top, - toReal_pow, Real.log_pow, EReal.coe_mul] - rfl + simp only [log, pow_eq_zero_iff', x_real.1.ne', false_and, ↓reduceIte, pow_eq_top_iff, + x_real.2.ne, toReal_pow, Real.log_pow, EReal.coe_mul, EReal.coe_coe_eq_natCast] theorem log_rpow {x : ℝ≥0∞} {y : ℝ} : log (x ^ y) = y * log x := by rcases lt_trichotomy y 0 with (y_neg | rfl | y_pos) · rcases ENNReal.trichotomy x with (rfl | rfl | x_real) - · simp only [ENNReal.zero_rpow_def y, not_lt_of_lt y_neg, ne_of_lt y_neg, log_top, log_zero] - exact Eq.symm (EReal.coe_mul_bot_of_neg y_neg) - · rw [ENNReal.top_rpow_of_neg y_neg, log_zero, log_top] - exact Eq.symm (EReal.coe_mul_top_of_neg y_neg) - · have x_ne_zero := Ne.symm (LT.lt.ne (ENNReal.toReal_pos_iff.1 x_real).1) - have x_ne_top := LT.lt.ne (ENNReal.toReal_pos_iff.1 x_real).2 + · simp only [ENNReal.zero_rpow_def y, not_lt_of_lt y_neg, y_neg.ne, if_false, log_top, + log_zero, EReal.coe_mul_bot_of_neg y_neg] + · rw [ENNReal.top_rpow_of_neg y_neg, log_zero, log_top, EReal.coe_mul_top_of_neg y_neg] + · have x_ne_zero := (ENNReal.toReal_pos_iff.1 x_real).1.ne' + have x_ne_top := (ENNReal.toReal_pos_iff.1 x_real).2.ne simp only [log, rpow_eq_zero_iff, x_ne_zero, false_and, x_ne_top, or_self, ↓reduceIte, rpow_eq_top_iff] norm_cast @@ -198,8 +190,8 @@ theorem log_rpow {x : ℝ≥0∞} {y : ℝ} : log (x ^ y) = y * log x := by · rcases ENNReal.trichotomy x with (rfl | rfl | x_real) · rw [ENNReal.zero_rpow_of_pos y_pos, log_zero, EReal.mul_bot_of_pos]; norm_cast · rw [ENNReal.top_rpow_of_pos y_pos, log_top, EReal.mul_top_of_pos]; norm_cast - · have x_ne_zero := Ne.symm (LT.lt.ne (ENNReal.toReal_pos_iff.1 x_real).1) - have x_ne_top := LT.lt.ne (ENNReal.toReal_pos_iff.1 x_real).2 + · have x_ne_zero := (ENNReal.toReal_pos_iff.1 x_real).1.ne' + have x_ne_top := (ENNReal.toReal_pos_iff.1 x_real).2.ne simp only [log, rpow_eq_zero_iff, x_ne_zero, false_and, x_ne_top, or_self, ↓reduceIte, rpow_eq_top_iff] norm_cast diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index 9fd198d9d716f..ccdc8da2c18ea 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -189,10 +189,8 @@ lemma getVert_cons_succ {u v w n} (p : G.Walk v w) (h : G.Adj u v) : lemma getVert_cons {u v w n} (p : G.Walk v w) (h : G.Adj u v) (hn : n ≠ 0) : (p.cons h).getVert n = p.getVert (n - 1) := by - obtain ⟨i, hi⟩ : ∃ (i : ℕ), i.succ = n := by - use n - 1; exact Nat.succ_pred_eq_of_ne_zero hn - rw [← hi] - simp only [Nat.succ_eq_add_one, getVert_cons_succ, Nat.add_sub_cancel] + obtain ⟨n, rfl⟩ := Nat.exists_eq_add_one_of_ne_zero hn + rw [getVert_cons_succ, Nat.add_sub_cancel] @[simp] theorem cons_append {u v w x : V} (h : G.Adj u v) (p : G.Walk v w) (q : G.Walk w x) : @@ -202,23 +200,21 @@ theorem cons_append {u v w x : V} (h : G.Adj u v) (p : G.Walk v w) (q : G.Walk w theorem cons_nil_append {u v w : V} (h : G.Adj u v) (p : G.Walk v w) : (cons h nil).append p = cons h p := rfl +@[simp] +theorem nil_append {u v : V} (p : G.Walk u v) : nil.append p = p := + rfl + @[simp] theorem append_nil {u v : V} (p : G.Walk u v) : p.append nil = p := by induction p with - | nil => rfl + | nil => rw [nil_append] | cons _ _ ih => rw [cons_append, ih] -@[simp] -theorem nil_append {u v : V} (p : G.Walk u v) : nil.append p = p := - rfl - theorem append_assoc {u v w x : V} (p : G.Walk u v) (q : G.Walk v w) (r : G.Walk w x) : p.append (q.append r) = (p.append q).append r := by induction p with - | nil => rfl - | cons h p' ih => - dsimp only [append] - rw [ih] + | nil => rw [nil_append, nil_append] + | cons h p' ih => rw [cons_append, cons_append, cons_append, ih] @[simp] theorem append_copy_copy {u v w u' v' w'} (p : G.Walk u v) (q : G.Walk v w) @@ -664,9 +660,8 @@ theorem head_darts_fst {G : SimpleGraph V} {a b : V} (p : G.Walk a b) (hp : p.da theorem getLast_darts_snd {G : SimpleGraph V} {a b : V} (p : G.Walk a b) (hp : p.darts ≠ []) : (p.darts.getLast hp).snd = b := by rw [← List.getLast_map (f := fun x : G.Dart ↦ x.snd)] - simp_rw [p.map_snd_darts, List.getLast_tail] - exact p.getLast_support - simpa + · simp_rw [p.map_snd_darts, List.getLast_tail, p.getLast_support] + · simpa @[simp] theorem edges_nil {u : V} : (nil : G.Walk u u).edges = [] := rfl diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index f3f8caf0ecd44..1ff8e427f3cb9 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -45,20 +45,15 @@ instance : WellFoundedLT ℕ∞ := inferInstanceAs (WellFoundedLT (WithTop ℕ)) instance : CharZero ℕ∞ := inferInstanceAs (CharZero (WithTop ℕ)) instance : IsWellOrder ℕ∞ (· < ·) where -instance : SuccAddOrder ℕ∞ := by - constructor - rintro (_ | _) - · rfl - · change ite .. = _ - simp - rfl - variable {m n : ℕ∞} /-- Lemmas about `WithTop` expect (and can output) `WithTop.some` but the normal form for coercion `ℕ → ℕ∞` is `Nat.cast`. -/ @[simp] theorem some_eq_coe : (WithTop.some : ℕ → ℕ∞) = Nat.cast := rfl +instance : SuccAddOrder ℕ∞ where + succ_eq_add_one x := by cases x <;> simp [SuccOrder.succ] + -- Porting note: `simp` and `norm_cast` can prove it --@[simp, norm_cast] theorem coe_zero : ((0 : ℕ) : ℕ∞) = 0 := diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index f09889ada8f6b..033d11b1cb4a5 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -725,7 +725,7 @@ theorem coe_zero {_m : MeasurableSpace α} : ⇑(0 : Measure α) = 0 := rfl @[simp] lemma _root_.MeasureTheory.OuterMeasure.toMeasure_zero - [ms : MeasurableSpace α](h : ms ≤ (0 : OuterMeasure α).caratheodory) : + [ms : MeasurableSpace α] (h : ms ≤ (0 : OuterMeasure α).caratheodory) : (0 : OuterMeasure α).toMeasure h = 0 := by ext s hs simp [hs] diff --git a/Mathlib/Order/RelSeries.lean b/Mathlib/Order/RelSeries.lean index fc2073f2ab1b0..d01a0e54fc8ee 100644 --- a/Mathlib/Order/RelSeries.lean +++ b/Mathlib/Order/RelSeries.lean @@ -758,7 +758,7 @@ lemma apply_add_index_le_apply_add_index_nat (p : LTSeries ℕ) (i j : Fin (p.le have ⟨j, hj⟩ := j simp only [Fin.mk_le_mk] at hij simp only at * - induction j, hij using Nat.le_induction with + induction j, hij using Nat.le_induction with | base => simp | succ j _hij ih => specialize ih (Nat.lt_of_succ_lt hj) diff --git a/Mathlib/Order/ScottContinuity.lean b/Mathlib/Order/ScottContinuity.lean index 00f7de8d741c2..511092cd0a000 100644 --- a/Mathlib/Order/ScottContinuity.lean +++ b/Mathlib/Order/ScottContinuity.lean @@ -71,7 +71,7 @@ lemma ScottContinuousOn.prodMk (hD : ∀ a b : α, a ≤ b → {a, b} ∈ D) rw [IsLUB, IsLeast, upperBounds] constructor · simp only [mem_image, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, mem_setOf_eq, - Prod.mk_le_mk] + Prod.mk_le_mk] intro b hb exact ⟨hf.monotone D hD (hda.1 hb), hg.monotone D hD (hda.1 hb)⟩ · intro ⟨p₁, p₂⟩ hp @@ -101,7 +101,7 @@ lemma ScottContinuous.scottContinuousOn {D : Set (Set α)} : ScottContinuous f → ScottContinuousOn D f := fun h _ _ d₂ d₃ _ hda => h d₂ d₃ hda protected theorem ScottContinuous.monotone (h : ScottContinuous f) : Monotone f := - h.scottContinuousOn.monotone univ (fun _ _ _ ↦ trivial) + h.scottContinuousOn.monotone univ (fun _ _ _ ↦ mem_univ _) @[simp] lemma ScottContinuous.id : ScottContinuous (id : α → α) := by simp [ScottContinuous] diff --git a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean index 2a11b704d5899..b2e2b120664d7 100644 --- a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean +++ b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean @@ -68,13 +68,14 @@ instance (priority := 100) isPredArchimedean_of_isSuccArchimedean [IsSuccArchime ⟨Nat.find h_exists, Nat.find_spec h_exists, fun m hmn ↦ Nat.find_min h_exists hmn⟩ refine ⟨n, ?_⟩ rw [← hn_eq] - induction' n with n - · simp only [Function.iterate_zero, id] - · rw [pred_succ_iterate_of_not_isMax] + cases n with + | zero => simp only [Function.iterate_zero, id] + | succ n => + rw [pred_succ_iterate_of_not_isMax] rw [Nat.succ_sub_succ_eq_sub, tsub_zero] suffices succ^[n] i < succ^[n.succ] i from not_isMax_of_lt this refine lt_of_le_of_ne ?_ ?_ - · rw [Function.iterate_succ'] + · rw [Function.iterate_succ_apply'] exact le_succ _ · rw [hn_eq] exact hn_lt_ne _ (Nat.lt_succ_self n) @@ -84,9 +85,9 @@ instance isSuccArchimedean_of_isPredArchimedean [IsPredArchimedean ι] : IsSuccA /-- In a linear `SuccOrder` that's also a `PredOrder`, `IsSuccArchimedean` and `IsPredArchimedean` are equivalent. -/ -theorem isSuccArchimedean_iff_isPredArchimedean : IsSuccArchimedean ι ↔ IsPredArchimedean ι := - ⟨fun _ => isPredArchimedean_of_isSuccArchimedean, - fun _ => isSuccArchimedean_of_isPredArchimedean⟩ +theorem isSuccArchimedean_iff_isPredArchimedean : IsSuccArchimedean ι ↔ IsPredArchimedean ι where + mp _ := isPredArchimedean_of_isSuccArchimedean + mpr _ := isSuccArchimedean_of_isPredArchimedean end LinearOrder diff --git a/Mathlib/Probability/Kernel/Composition.lean b/Mathlib/Probability/Kernel/Composition.lean index 43797429a7831..2a16eb0159a62 100644 --- a/Mathlib/Probability/Kernel/Composition.lean +++ b/Mathlib/Probability/Kernel/Composition.lean @@ -113,7 +113,7 @@ theorem compProdFun_iUnion (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSF Set.mem_empty_iff_false] using hf_disj hij hbci hbcj · exact fun i ↦ measurable_prod_mk_left (hf_meas i) rw [h_tsum, lintegral_tsum] - · rfl + · simp [compProdFun] · intro i have hm : MeasurableSet {p : (α × β) × γ | (p.1.2, p.2) ∈ f i} := measurable_fst.snd.prod_mk measurable_snd (hf_meas i) @@ -320,8 +320,7 @@ theorem compProd_restrict {s : Set β} {t : Set γ} (hs : MeasurableSet s) (ht : classical rw [Set.indicator_apply] split_ifs with h - · simp only [h, true_and] - rfl + · simp only [h, true_and, Set.inter_def, Set.mem_setOf] · simp only [h, false_and, and_false, Set.setOf_false, measure_empty] simp_rw [this] rw [lintegral_indicator _ hs] @@ -593,8 +592,7 @@ theorem map_of_not_measurable (κ : Kernel α β) {f : β → γ} (hf : ¬(Measu simp [map, hf] theorem map_apply (κ : Kernel α β) (hf : Measurable f) (a : α) : map κ f a = (κ a).map f := by - simp only [map, hf, ↓reduceDIte, mapOfMeasurable] - rfl + simp only [map, hf, ↓reduceDIte, mapOfMeasurable, coe_mk] theorem map_apply' (κ : Kernel α β) (hf : Measurable f) (a : α) {s : Set γ} (hs : MeasurableSet s) : map κ f a s = κ a (f ⁻¹' s) := by rw [map_apply _ hf, Measure.map_apply hf hs] @@ -916,8 +914,8 @@ lemma fst_map_prod (κ : Kernel α β) {f : β → γ} {g : β → δ} (hg : Mea fst (map κ (fun x ↦ (f x, g x))) = map κ f := by by_cases hf : Measurable f · ext x s hs - rw [fst_apply' _ _ hs, map_apply' _ (hf.prod hg), map_apply' _ hf _ hs] - · rfl + rw [fst_apply' _ _ hs, map_apply' _ (hf.prod hg) _, map_apply' _ hf _ hs] + · simp only [Set.preimage, Set.mem_setOf] · exact measurable_fst hs · have : ¬ Measurable (fun x ↦ (f x, g x)) := by contrapose! hf; exact hf.fst @@ -993,7 +991,7 @@ lemma snd_map_prod (κ : Kernel α β) {f : β → γ} {g : β → δ} (hf : Mea by_cases hg : Measurable g · ext x s hs rw [snd_apply' _ _ hs, map_apply' _ (hf.prod hg), map_apply' _ hg _ hs] - · rfl + · simp only [Set.preimage, Set.mem_setOf] · exact measurable_snd hs · have : ¬ Measurable (fun x ↦ (f x, g x)) := by contrapose! hg; exact hg.snd diff --git a/Mathlib/RingTheory/Valuation/ValExtension.lean b/Mathlib/RingTheory/Valuation/ValExtension.lean index 472b2f2c09450..888369fc04bb9 100644 --- a/Mathlib/RingTheory/Valuation/ValExtension.lean +++ b/Mathlib/RingTheory/Valuation/ValExtension.lean @@ -89,8 +89,7 @@ end algebraMap instance id : IsValExtension vR vR where val_isEquiv_comap := by - simp only [Algebra.id.map_eq_id, comap_id] - rfl + simp only [Algebra.id.map_eq_id, comap_id, IsEquiv.refl] section integer @@ -108,8 +107,7 @@ theorem ofComapInteger (h : vA.integer.comap (algebraMap K A) = vK.integer) : val_isEquiv_comap := by rw [isEquiv_iff_val_le_one] intro x - rw [← Valuation.mem_integer_iff, ← Valuation.mem_integer_iff, ← h] - rfl + simp_rw [← Valuation.mem_integer_iff, ← h, Subring.mem_comap, mem_integer_iff, comap_apply] instance instAlgebraInteger : Algebra vR.integer vA.integer where smul r a := ⟨r • a, diff --git a/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean b/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean index 10923f5231954..988d2a453721f 100644 --- a/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean +++ b/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean @@ -168,9 +168,8 @@ theorem embedding_restrictScalars : @[continuity, fun_prop] theorem continuous_restrictScalars : - Continuous - (restrictScalars 𝕜' : E [⋀^ι]→L[𝕜] F → E [⋀^ι]→L[𝕜'] F) := - embedding_restrictScalars.continuous + Continuous (restrictScalars 𝕜' : E [⋀^ι]→L[𝕜] F → E [⋀^ι]→L[𝕜'] F) := + embedding_restrictScalars.continuous variable (𝕜') in /-- `ContinuousMultilinearMap.restrictScalars` as a `ContinuousLinearMap`. -/ diff --git a/Mathlib/Topology/OmegaCompletePartialOrder.lean b/Mathlib/Topology/OmegaCompletePartialOrder.lean index ddf55f07e81c4..89f1e3ee2fa58 100644 --- a/Mathlib/Topology/OmegaCompletePartialOrder.lean +++ b/Mathlib/Topology/OmegaCompletePartialOrder.lean @@ -48,7 +48,7 @@ theorem IsOpen.inter (s t : Set α) : IsOpen α s → IsOpen α t → IsOpen α theorem isOpen_sUnion (s : Set (Set α)) (hs : ∀ t ∈ s, IsOpen α t) : IsOpen α (⋃₀ s) := by simp only [IsOpen] at hs ⊢ - convert CompleteLattice.ωScottContinuous.sSup hs + convert CompleteLattice.ωScottContinuous.sSup hs aesop theorem IsOpen.isUpperSet {s : Set α} (hs : IsOpen α s) : IsUpperSet s := hs.monotone @@ -78,7 +78,7 @@ def notBelow := theorem notBelow_isOpen : IsOpen (notBelow y) := by have h : Monotone (notBelow y) := fun x z hle ↦ mt hle.trans - change ωScottContinuous fun x ↦ x ∈ notBelow y + dsimp only [IsOpen, TopologicalSpace.IsOpen, Scott.IsOpen] rw [ωScottContinuous_iff_monotone_map_ωSup] refine ⟨h, fun c ↦ eq_of_forall_ge_iff fun z ↦ ?_⟩ simp only [ωSup_le_iff, notBelow, mem_setOf_eq, le_Prop_eq, OrderHom.coe_mk, Chain.map_coe, @@ -117,5 +117,6 @@ theorem continuous_of_scottContinuous {α β} [OmegaCompletePartialOrder α] (hf : ωScottContinuous f) : Continuous f := by rw [continuous_def] intro s hs - change ωScottContinuous (s ∘ f) + dsimp only [IsOpen, TopologicalSpace.IsOpen, Scott.IsOpen] + simp_rw [mem_preimage, mem_def, ← Function.comp_def] apply ωScottContinuous.comp hs hf diff --git a/Mathlib/Topology/Order/Monotone.lean b/Mathlib/Topology/Order/Monotone.lean index 0493d4d868c9c..c807d80f962d5 100644 --- a/Mathlib/Topology/Order/Monotone.lean +++ b/Mathlib/Topology/Order/Monotone.lean @@ -52,8 +52,8 @@ supremum to the indexed supremum of the composition. -/ theorem Monotone.map_ciSup_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iSup g)) (Mf : Monotone f) (bdd : BddAbove (range g) := by bddDefault) : f (⨆ i, g i) = ⨆ i, f (g i) := by - rw [iSup, Monotone.map_csSup_of_continuousAt Cf Mf (range_nonempty g) bdd, ← range_comp, iSup] - rfl + rw [iSup, Monotone.map_csSup_of_continuousAt Cf Mf (range_nonempty g) bdd, ← range_comp, iSup, + comp_def] @[deprecated (since := "2024-08-26")] alias Monotone.map_iSup_of_continuousAt' := Monotone.map_ciSup_of_continuousAt @@ -81,8 +81,8 @@ infimum to the indexed infimum of the composition. -/ theorem Monotone.map_ciInf_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iInf g)) (Mf : Monotone f) (bdd : BddBelow (range g) := by bddDefault) : f (⨅ i, g i) = ⨅ i, f (g i) := by - rw [iInf, Monotone.map_csInf_of_continuousAt Cf Mf (range_nonempty g) bdd, ← range_comp, iInf] - rfl + rw [iInf, Monotone.map_csInf_of_continuousAt Cf Mf (range_nonempty g) bdd, ← range_comp, iInf, + comp_def] @[deprecated (since := "2024-08-26")] alias Monotone.map_iInf_of_continuousAt' := Monotone.map_ciInf_of_continuousAt @@ -110,8 +110,8 @@ infimum to the indexed supremum of the composition. -/ theorem Antitone.map_ciInf_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iInf g)) (Af : Antitone f) (bdd : BddBelow (range g) := by bddDefault) : f (⨅ i, g i) = ⨆ i, f (g i) := by - rw [iInf, Antitone.map_csInf_of_continuousAt Cf Af (range_nonempty g) bdd, ← range_comp, iSup] - rfl + rw [iInf, Antitone.map_csInf_of_continuousAt Cf Af (range_nonempty g) bdd, ← range_comp, iSup, + comp_def] @[deprecated (since := "2024-08-26")] alias Antitone.map_iInf_of_continuousAt' := Antitone.map_ciInf_of_continuousAt @@ -139,8 +139,8 @@ indexed supremum to the indexed infimum of the composition. -/ theorem Antitone.map_ciSup_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iSup g)) (Af : Antitone f) (bdd : BddAbove (range g) := by bddDefault) : f (⨆ i, g i) = ⨅ i, f (g i) := by - rw [iSup, Antitone.map_csSup_of_continuousAt Cf Af (range_nonempty g) bdd, ← range_comp, iInf] - rfl + rw [iSup, Antitone.map_csSup_of_continuousAt Cf Af (range_nonempty g) bdd, ← range_comp, iInf, + comp_def] @[deprecated (since := "2024-08-26")] alias Antitone.map_iSup_of_continuousAt' := Antitone.map_ciSup_of_continuousAt @@ -184,7 +184,7 @@ a `Sort`, then it sends this indexed supremum to the indexed supremum of the com theorem Monotone.map_iSup_of_continuousAt {ι : Sort*} {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iSup g)) (Mf : Monotone f) (fbot : f ⊥ = ⊥) : f (⨆ i, g i) = ⨆ i, f (g i) := by - rw [iSup, Mf.map_sSup_of_continuousAt Cf fbot, ← range_comp, iSup]; rfl + rw [iSup, Mf.map_sSup_of_continuousAt Cf fbot, ← range_comp, iSup, comp_def] /-- A monotone function `f` sending `top` to `top` and continuous at the infimum of a set sends this infimum to the infimum of the image of this set. -/ From 38dfa07f6fae335a6df1eed502afb7783ced97dd Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:31:00 +0000 Subject: [PATCH 027/170] chore: avoid Finset dependency in Algebra.Algebra.Defs (#16893) --- Mathlib/Algebra/Algebra/Basic.lean | 18 ++++++++++++++++++ Mathlib/Algebra/Algebra/Defs.lean | 22 +--------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index 27b7ad24b9d20..6b638c7aa5b45 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -522,3 +522,21 @@ lemma LinearEquiv.extendScalarsOfSurjective_symm (f : M ≃ₗ[R] N) : (f.extendScalarsOfSurjective h).symm = f.symm.extendScalarsOfSurjective h := rfl end surjective + +namespace algebraMap + +section CommSemiringCommSemiring + +variable {R A : Type*} [CommSemiring R] [CommSemiring A] [Algebra R A] {ι : Type*} {s : Finset ι} + +@[norm_cast] +theorem coe_prod (a : ι → R) : (↑(∏ i ∈ s, a i : R) : A) = ∏ i ∈ s, (↑(a i) : A) := + map_prod (algebraMap R A) a s + +@[norm_cast] +theorem coe_sum (a : ι → R) : ↑(∑ i ∈ s, a i) = ∑ i ∈ s, (↑(a i) : A) := + map_sum (algebraMap R A) a s + +end CommSemiringCommSemiring + +end algebraMap diff --git a/Mathlib/Algebra/Algebra/Defs.lean b/Mathlib/Algebra/Algebra/Defs.lean index 10be082a45ea6..0393439d7bb1f 100644 --- a/Mathlib/Algebra/Algebra/Defs.lean +++ b/Mathlib/Algebra/Algebra/Defs.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Yury Kudryashov -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Module.LinearMap.Defs /-! @@ -82,6 +81,7 @@ the second approach only when you need to weaken a condition on either `R` or `A -/ assert_not_exists Field +assert_not_exists Finset assert_not_exists Module.End universe u v w u₁ v₁ @@ -165,26 +165,6 @@ theorem coe_sub (a b : R) : end CommRingRing -section CommSemiringCommSemiring - -variable {R A : Type*} [CommSemiring R] [CommSemiring A] [Algebra R A] - --- direct to_additive fails because of some mix-up with polynomials -@[norm_cast] -theorem coe_prod {ι : Type*} {s : Finset ι} (a : ι → R) : - (↑(∏ i ∈ s, a i : R) : A) = ∏ i ∈ s, (↑(a i) : A) := - map_prod (algebraMap R A) a s - --- to_additive fails for some reason -@[norm_cast] -theorem coe_sum {ι : Type*} {s : Finset ι} (a : ι → R) : - ↑(∑ i ∈ s, a i) = ∑ i ∈ s, (↑(a i) : A) := - map_sum (algebraMap R A) a s - --- Porting note: removed attribute [to_additive] coe_prod; why should this be a `to_additive`? - -end CommSemiringCommSemiring - end algebraMap /-- Creating an algebra from a morphism to the center of a semiring. -/ From 617f330d3ad464588c4abd6a97fd8ebd200c979f Mon Sep 17 00:00:00 2001 From: YnirPaz Date: Wed, 18 Sep 2024 21:33:18 +0000 Subject: [PATCH 028/170] feat(SetTheory/Ordinal/Basic): added ord_zero_iff lemma (#16912) Prove `ord_zero_iff`. --- Mathlib/SetTheory/Ordinal/Basic.lean | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index f69dcba126f7b..4fe487ab74e97 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -1277,6 +1277,18 @@ theorem ord_injective : Injective ord := by intro c c' h rw [← card_ord c, ← card_ord c', h] +@[simp] +theorem ord_inj {a b : Cardinal} : a.ord = b.ord ↔ a = b := + ord_injective.eq_iff + +@[simp] +theorem ord_eq_zero {a : Cardinal} : a.ord = 0 ↔ a = 0 := + ord_injective.eq_iff' ord_zero + +@[simp] +theorem ord_eq_one {a : Cardinal} : a.ord = 1 ↔ a = 1 := + ord_injective.eq_iff' ord_one + /-- The ordinal corresponding to a cardinal `c` is the least ordinal whose cardinal is `c`. This is the order-embedding version. For the regular function, see `ord`. -/ From f5c515a5fad06d7c8557c9a049288b6216b5424f Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Wed, 18 Sep 2024 22:16:33 +0000 Subject: [PATCH 029/170] feat(CategoryTheory/Galois): universal property of fundamental group (#16673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We introduce a universal property for the automorphism group of a fiber functor for any topological group. In the further development of the Galois categories API, an arbitrary topological group satisfying this universal property shall be used in the place of `Aut F`, to prepare for later usages of this API in the case of e.g. `G` being the absolute Galois group of a field `k` and `F` being the fiber functor of the category of finite, étale `k`-algebras. --- Mathlib.lean | 1 + .../CategoryTheory/Galois/Decomposition.lean | 9 + .../Galois/IsFundamentalgroup.lean | 288 ++++++++++++++++++ Mathlib/CategoryTheory/Galois/Topology.lean | 2 +- 4 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean diff --git a/Mathlib.lean b/Mathlib.lean index afa21ce257b10..2a4a1d5880540 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1531,6 +1531,7 @@ import Mathlib.CategoryTheory.Galois.Decomposition import Mathlib.CategoryTheory.Galois.Examples import Mathlib.CategoryTheory.Galois.Full import Mathlib.CategoryTheory.Galois.GaloisObjects +import Mathlib.CategoryTheory.Galois.IsFundamentalgroup import Mathlib.CategoryTheory.Galois.Prorepresentability import Mathlib.CategoryTheory.Galois.Topology import Mathlib.CategoryTheory.Generator diff --git a/Mathlib/CategoryTheory/Galois/Decomposition.lean b/Mathlib/CategoryTheory/Galois/Decomposition.lean index b9febf20bbfc8..367dfd4597ae6 100644 --- a/Mathlib/CategoryTheory/Galois/Decomposition.lean +++ b/Mathlib/CategoryTheory/Galois/Decomposition.lean @@ -308,6 +308,15 @@ lemma exists_hom_from_galois_of_connected (X : C) [IsConnected X] : ∃ (A : C) (_ : A ⟶ X), IsGalois A := exists_hom_from_galois_of_fiber_nonempty F X inferInstance +/-- To check equality of natural transformations `F ⟶ G`, it suffices to check it on +Galois objects. -/ +lemma natTrans_ext_of_isGalois {G : C ⥤ FintypeCat.{w}} {t s : F ⟶ G} + (h : ∀ (X : C) [IsGalois X], t.app X = s.app X) : + t = s := by + ext X x + obtain ⟨A, f, a, _, rfl⟩ := exists_hom_from_galois_of_fiber F X x + rw [FunctorToFintypeCat.naturality, FunctorToFintypeCat.naturality, h A] + end GaloisRep end PreGaloisCategory diff --git a/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean b/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean new file mode 100644 index 0000000000000..f5398eaad344f --- /dev/null +++ b/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean @@ -0,0 +1,288 @@ +/- +Copyright (c) 2024 Christian Merten. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Merten +-/ +import Mathlib.CategoryTheory.Galois.Basic +import Mathlib.CategoryTheory.Galois.Topology +import Mathlib.CategoryTheory.Galois.Prorepresentability +import Mathlib.Topology.Algebra.OpenSubgroup + +/-! + +# Universal property of fundamental group + +Let `C` be a Galois category with fiber functor `F`. While in informal mathematics, we tend to +identify known groups from other contexts (e.g. the absolute Galois group of a field) with +the automorphism group `Aut F` of certain fiber functors `F`, this causes friction in formalization. + +Hence, in this file we develop conditions when a topological group `G` is canonically isomorphic to +the automorphism group `Aut F` of `F`. Consequently, the API for Galois categories and their fiber +functors should be stated in terms of an abstract topological group `G` satisfying +`IsFundamentalGroup` in the places where `Aut F` would appear. + +## Main definition + +Given a compact, topological group `G` with an action on `F.obj X` on each `X`, we say that +`G` is a fundamental group of `F` (`IsFundamentalGroup F G`), if + +- `naturality`: the `G`-action on `F.obj X` is compatible with morphisms in `C` +- `transitive_of_isGalois`: `G` acts transitively on `F.obj X` for all Galois objects `X : C` +- `continuous_smul`: the action of `G` on `F.obj X` is continuous if `F.obj X` is equipped with the + discrete topology for all `X : C`. +- `non_trivial': if `g : G` acts trivial on all `F.obj X`, then `g = 1`. + +Given this data, we define `toAut F G : G →* Aut F` in the natural way. + +## Main results + +- `toAut_bijective`: `toAut F G` is a group isomorphism given `IsFundamentalGroup F G`. +- `toAut_isHomeomorph`: `toAut F G` is a homeomorphism given `IsFundamentalGroup F G`. + +## TODO + +- Develop further equivalent conditions, in particular, relate the condition `non_trivial` with + `G` being a `T2Space`. + +-/ +universe u₁ u₂ w + +namespace CategoryTheory + +namespace PreGaloisCategory + +open Limits Functor + +variable {C : Type u₁} [Category.{u₂} C] (F : C ⥤ FintypeCat.{w}) + +section + +variable (G : Type*) [Group G] [∀ X, MulAction G (F.obj X)] + +/-- We say `G` acts naturally on the fibers of `F` if for every `f : X ⟶ Y`, the `G`-actions +on `F.obj X` and `F.obj Y` are compatible with `F.map f`. -/ +class IsNaturalSMul : Prop where + naturality (g : G) {X Y : C} (f : X ⟶ Y) (x : F.obj X) : F.map f (g • x) = g • F.map f x + +variable {G} in +@[simps!] +private def isoOnObj (g : G) (X : C) : F.obj X ≅ F.obj X := + FintypeCat.equivEquivIso <| { + toFun := fun x ↦ g • x + invFun := fun x ↦ g⁻¹ • x + left_inv := fun _ ↦ by simp + right_inv := fun _ ↦ by simp + } + +variable [IsNaturalSMul F G] + +/-- If `G` acts naturally on `F.obj X` for each `X : C`, this is the canonical +group homomorphism into the automorphism group of `F`. -/ +def toAut : G →* Aut F where + toFun g := NatIso.ofComponents (isoOnObj F g) <| by + intro X Y f + ext + simp [IsNaturalSMul.naturality] + map_one' := by + ext + simp only [NatIso.ofComponents_hom_app, isoOnObj_hom, one_smul] + rfl + map_mul' := by + intro g h + ext X x + simp only [NatIso.ofComponents_hom_app, isoOnObj_hom, mul_smul] + rfl + +variable {G} in +@[simp] +lemma toAut_hom_app_apply (g : G) {X : C} (x : F.obj X) : (toAut F G g).hom.app X x = g • x := + rfl + +/-- `toAut` is injective, if only the identity acts trivially on every fiber. -/ +lemma toAut_injective_of_non_trivial (h : ∀ (g : G), (∀ (X : C) (x : F.obj X), g • x = x) → g = 1) : + Function.Injective (toAut F G) := by + rw [← MonoidHom.ker_eq_bot_iff, eq_bot_iff] + intro g (hg : toAut F G g = 1) + refine h g (fun X x ↦ ?_) + have : (toAut F G g).hom.app X = 𝟙 (F.obj X) := by + rw [hg] + rfl + rw [← toAut_hom_app_apply, this, FintypeCat.id_apply] + +variable [GaloisCategory C] [FiberFunctor F] + +lemma toAut_continuous [TopologicalSpace G] [TopologicalGroup G] + [∀ (X : C), ContinuousSMul G (F.obj X)] : + Continuous (toAut F G) := by + apply continuous_of_continuousAt_one + rw [continuousAt_def, map_one] + intro A hA + obtain ⟨X, _, hX⟩ := ((nhds_one_has_basis_stabilizers F).mem_iff' A).mp hA + rw [mem_nhds_iff] + exact ⟨MulAction.stabilizer G X.pt, Set.preimage_mono (f := toAut F G) hX, + stabilizer_isOpen G X.pt, one_mem _⟩ + +variable {G} + +lemma action_ext_of_isGalois {t : F ⟶ F} {X : C} [IsGalois X] {g : G} (x : F.obj X) + (hg : g • x = t.app X x) (y : F.obj X) : g • y = t.app X y := by + obtain ⟨φ, (rfl : F.map φ.hom y = x)⟩ := MulAction.exists_smul_eq (Aut X) y x + have : Function.Injective (F.map φ.hom) := + ConcreteCategory.injective_of_mono_of_preservesPullback (F.map φ.hom) + apply this + rw [IsNaturalSMul.naturality, hg, FunctorToFintypeCat.naturality] + +variable (G) + +lemma toAut_surjective_isGalois (t : Aut F) (X : C) [IsGalois X] + [MulAction.IsPretransitive G (F.obj X)] : + ∃ (g : G), ∀ (x : F.obj X), g • x = t.hom.app X x := by + obtain ⟨a⟩ := nonempty_fiber_of_isConnected F X + obtain ⟨g, hg⟩ := MulAction.exists_smul_eq G a (t.hom.app X a) + exact ⟨g, action_ext_of_isGalois F _ hg⟩ + +lemma toAut_surjective_isGalois_finite_family (t : Aut F) {ι : Type*} [Finite ι] (X : ι → C) + [∀ i, IsGalois (X i)] (h : ∀ (X : C) [IsGalois X], MulAction.IsPretransitive G (F.obj X)) : + ∃ (g : G), ∀ (i : ι) (x : F.obj (X i)), g • x = t.hom.app (X i) x := by + let x (i : ι) : F.obj (X i) := (nonempty_fiber_of_isConnected F (X i)).some + let P : C := ∏ᶜ X + letI : Fintype ι := Fintype.ofFinite ι + let is₁ : F.obj P ≅ ∏ᶜ fun i ↦ (F.obj (X i)) := PreservesProduct.iso F X + let is₂ : (∏ᶜ fun i ↦ F.obj (X i) : FintypeCat) ≃ ∀ i, F.obj (X i) := + Limits.FintypeCat.productEquiv (fun i ↦ (F.obj (X i))) + let px : F.obj P := is₁.inv (is₂.symm x) + have hpx (i : ι) : F.map (Pi.π X i) px = x i := by + simp only [px, is₁, is₂, ← piComparison_comp_π, ← PreservesProduct.iso_hom] + simp only [FintypeCat.comp_apply, FintypeCat.inv_hom_id_apply, + FintypeCat.productEquiv_symm_comp_π_apply] + obtain ⟨A, f, a, _, hfa⟩ := exists_hom_from_galois_of_fiber F P px + obtain ⟨g, hg⟩ := toAut_surjective_isGalois F G t A + refine ⟨g, fun i y ↦ action_ext_of_isGalois F (x i) ?_ _⟩ + rw [← hpx i, ← IsNaturalSMul.naturality, FunctorToFintypeCat.naturality, + ← hfa, FunctorToFintypeCat.naturality, ← IsNaturalSMul.naturality, hg] + +open Pointwise + +/-- If `G` is a compact, topological group that acts continuously and naturally on the +fibers of `F`, `toAut F G` is surjective if and only if it acts transitively on the fibers +of all Galois objects. This is the `if` direction. For the `only if` see +`isPretransitive_of_surjective`. -/ +lemma toAut_surjective_of_isPretransitive [TopologicalSpace G] [TopologicalGroup G] [CompactSpace G] + [∀ (X : C), ContinuousSMul G (F.obj X)] + (h : ∀ (X : C) [IsGalois X], MulAction.IsPretransitive G (F.obj X)) : + Function.Surjective (toAut F G) := by + intro t + choose gi hgi using (fun X : PointedGaloisObject F ↦ toAut_surjective_isGalois F G t X) + let cl (X : PointedGaloisObject F) : Set G := gi X • MulAction.stabilizer G X.pt + let c : Set G := ⋂ i, cl i + have hne : c.Nonempty := by + rw [← Set.univ_inter c] + apply CompactSpace.isCompact_univ.inter_iInter_nonempty + · intro X + apply IsClosed.leftCoset + exact Subgroup.isClosed_of_isOpen _ (stabilizer_isOpen G X.pt) + · intro s + rw [Set.univ_inter] + obtain ⟨gs, hgs⟩ := + toAut_surjective_isGalois_finite_family F G t (fun X : s ↦ X.val.obj) h + use gs + simp only [Set.mem_iInter] + intro X hXmem + rw [mem_leftCoset_iff, SetLike.mem_coe, MulAction.mem_stabilizer_iff, mul_smul, + hgs ⟨X, hXmem⟩, ← hgi X, inv_smul_smul] + obtain ⟨g, hg⟩ := hne + refine ⟨g, Iso.ext <| natTrans_ext_of_isGalois _ <| fun X _ ↦ ?_⟩ + ext x + simp only [toAut_hom_app_apply] + have : g ∈ (gi ⟨X, x, inferInstance⟩ • MulAction.stabilizer G x : Set G) := by + simp only [Set.mem_iInter, c] at hg + exact hg _ + obtain ⟨s, (hsmem : s • x = x), (rfl : gi ⟨X, x, inferInstance⟩ • s = _)⟩ := this + rw [smul_eq_mul, mul_smul, hsmem] + exact hgi ⟨X, x, inferInstance⟩ x + +/-- If `toAut F G` is surjective, then `G` acts transitively on the fibers of connected objects. +For a converse see `toAut_surjective`. -/ +lemma isPretransitive_of_surjective (h : Function.Surjective (toAut F G)) (X : C) + [IsConnected X] : MulAction.IsPretransitive G (F.obj X) where + exists_smul_eq x y := by + obtain ⟨t, ht⟩ := MulAction.exists_smul_eq (Aut F) x y + obtain ⟨g, rfl⟩ := h t + exact ⟨g, ht⟩ + +end + +section + +variable [GaloisCategory C] +variable (G : Type*) [Group G] [∀ (X : C), MulAction G (F.obj X)] + +/-- A compact, topological group `G` with a natural action on `F.obj X` for each `X : C` +is a fundamental group of `F`, if `G` acts transitively on the fibers of Galois objects, +the action on `F.obj X` is continuous for all `X : C` and the only trivally acting element of `G` +is the identity. -/ +class IsFundamentalGroup [TopologicalSpace G] [TopologicalGroup G] [CompactSpace G] + extends IsNaturalSMul F G : Prop where + transitive_of_isGalois (X : C) [IsGalois X] : MulAction.IsPretransitive G (F.obj X) + continuous_smul (X : C) : ContinuousSMul G (F.obj X) + non_trivial' (g : G) : (∀ (X : C) (x : F.obj X), g • x = x) → g = 1 + +namespace IsFundamentalGroup + +attribute [instance] continuous_smul transitive_of_isGalois + +variable {G} [TopologicalSpace G] [TopologicalGroup G] [CompactSpace G] [IsFundamentalGroup F G] + +lemma non_trivial (g : G) (h : ∀ (X : C) (x : F.obj X), g • x = x) : g = 1 := + IsFundamentalGroup.non_trivial' g h + +end IsFundamentalGroup + +variable [FiberFunctor F] + +/-- `Aut F` is a fundamental group for `F`. -/ +instance : IsFundamentalGroup F (Aut F) where + naturality g X Y f x := (FunctorToFintypeCat.naturality F F g.hom f x).symm + transitive_of_isGalois X := FiberFunctor.isPretransitive_of_isConnected F X + continuous_smul X := continuousSMul_aut_fiber F X + non_trivial' g h := by + ext X x + exact h X x + +variable [TopologicalSpace G] [TopologicalGroup G] [CompactSpace G] [IsFundamentalGroup F G] + +lemma toAut_bijective : Function.Bijective (toAut F G) where + left := toAut_injective_of_non_trivial F G IsFundamentalGroup.non_trivial' + right := toAut_surjective_of_isPretransitive F G IsFundamentalGroup.transitive_of_isGalois + +instance (X : C) [IsConnected X] : MulAction.IsPretransitive G (F.obj X) := + isPretransitive_of_surjective F G (toAut_bijective F G).surjective X + +/-- If `G` is the fundamental group for `F`, it is isomorphic to `Aut F` as groups and +this isomorphism is also a homeomorphism (see `toAutMulEquiv_isHomeomorph`). -/ +noncomputable def toAutMulEquiv : G ≃* Aut F := + MulEquiv.ofBijective (toAut F G) (toAut_bijective F G) + +lemma toAut_isHomeomorph : IsHomeomorph (toAut F G) := by + rw [isHomeomorph_iff_continuous_bijective] + exact ⟨toAut_continuous F G, toAut_bijective F G⟩ + +lemma toAutMulEquiv_isHomeomorph : IsHomeomorph (toAutMulEquiv F G) := + toAut_isHomeomorph F G + +/-- If `G` is a fundamental group for `F`, it is canonically homeomorphic to `Aut F`. -/ +noncomputable def toAutHomeo : G ≃ₜ Aut F := (toAut_isHomeomorph F G).homeomorph + +variable {G} + +@[simp] +lemma toAutMulEquiv_apply (g : G) : toAutMulEquiv F G g = toAut F G g := rfl + +@[simp] +lemma toAutHomeo_apply (g : G) : toAutHomeo F G g = toAut F G g := rfl + +end + +end PreGaloisCategory + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Galois/Topology.lean b/Mathlib/CategoryTheory/Galois/Topology.lean index c896d52e004ff..62e4145b36bc7 100644 --- a/Mathlib/CategoryTheory/Galois/Topology.lean +++ b/Mathlib/CategoryTheory/Galois/Topology.lean @@ -28,7 +28,7 @@ namespace PreGaloisCategory open Functor -variable {C : Type u₁} [Category.{u₂} C] (F : C ⥤ FintypeCat.{u₂}) +variable {C : Type u₁} [Category.{u₂} C] (F : C ⥤ FintypeCat.{w}) /-- For a functor `F : C ⥤ FintypeCat`, the canonical embedding of `Aut F` into the product over `Aut (F.obj X)` for all objects `X`. -/ From 81fe23e70560c74b32813fbe679e4c7e0f93ac6c Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Wed, 18 Sep 2024 22:25:31 +0000 Subject: [PATCH 030/170] feat(MvPowerSeries.LexOrder): lexicographic order of multivariate power series (#14981) Define the order of multivariate power series with respect to the lexicographic order on monomials. Prove that the ring of multivariate power series over a domain is a domain. Extension to some rings of Hahn series --- Mathlib.lean | 1 + Mathlib/Order/Basic.lean | 4 + .../RingTheory/HahnSeries/PowerSeries.lean | 12 ++ .../RingTheory/MvPowerSeries/LexOrder.lean | 189 ++++++++++++++++++ .../MvPowerSeries/NoZeroDivisors.lean | 11 +- 5 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 Mathlib/RingTheory/MvPowerSeries/LexOrder.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2a4a1d5880540..9dc2fa945abee 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3955,6 +3955,7 @@ import Mathlib.RingTheory.MvPolynomial.Tower import Mathlib.RingTheory.MvPolynomial.WeightedHomogeneous import Mathlib.RingTheory.MvPowerSeries.Basic import Mathlib.RingTheory.MvPowerSeries.Inverse +import Mathlib.RingTheory.MvPowerSeries.LexOrder import Mathlib.RingTheory.MvPowerSeries.NoZeroDivisors import Mathlib.RingTheory.MvPowerSeries.Trunc import Mathlib.RingTheory.Nakayama diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 066ea4bab3a3a..628c729ea2354 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -711,6 +711,10 @@ instance instLinearOrder (α : Type*) [LinearOrder α] : LinearOrder αᵒᵈ wh decidableLE := (inferInstance : DecidableRel (fun a b : α ↦ b ≤ a)) decidableLT := (inferInstance : DecidableRel (fun a b : α ↦ b < a)) +/-- The opposite linear order to a given linear order -/ +def _root_.LinearOrder.swap (α : Type*) (_ : LinearOrder α) : LinearOrder α := + inferInstanceAs <| LinearOrder (OrderDual α) + instance : ∀ [Inhabited α], Inhabited αᵒᵈ := fun [x : Inhabited α] => x theorem Preorder.dual_dual (α : Type*) [H : Preorder α] : OrderDual.instPreorder αᵒᵈ = H := diff --git a/Mathlib/RingTheory/HahnSeries/PowerSeries.lean b/Mathlib/RingTheory/HahnSeries/PowerSeries.lean index 1441d746ae5c7..094a71acddd64 100644 --- a/Mathlib/RingTheory/HahnSeries/PowerSeries.lean +++ b/Mathlib/RingTheory/HahnSeries/PowerSeries.lean @@ -5,6 +5,7 @@ Authors: Aaron Anderson -/ import Mathlib.RingTheory.HahnSeries.Multiplication import Mathlib.RingTheory.PowerSeries.Basic +import Mathlib.RingTheory.MvPowerSeries.NoZeroDivisors import Mathlib.Data.Finsupp.PWO /-! @@ -18,6 +19,11 @@ we get the more familiar semiring of formal power series with coefficients in `R * `toPowerSeries` the isomorphism from `HahnSeries ℕ R` to `PowerSeries R`. * `ofPowerSeries` the inverse, casting a `PowerSeries R` to a `HahnSeries ℕ R`. +## Instances + * For `Finite σ`, the instance `NoZeroDivisors (HahnSeries (σ →₀ ℕ) R)`, + deduced from the case of `MvPowerSeries` + The case of `HahnSeries ℕ R` is taken care of by `instNoZeroDivisors`. + ## TODO * Build an API for the variable `X` (defined to be `single 1 1 : HahnSeries Γ R`) in analogy to `X : R[X]` and `X : PowerSeries R` @@ -166,6 +172,12 @@ def toMvPowerSeries {σ : Type*} [Finite σ] : HahnSeries (σ →₀ ℕ) R ≃+ variable {σ : Type*} [Finite σ] +-- TODO : generalize to all (?) rings of Hahn Series +/-- If R has no zero divisors and `σ` is finite, +then `HahnSeries (σ →₀ ℕ) R` has no zero divisors -/ +instance [NoZeroDivisors R] : NoZeroDivisors (HahnSeries (σ →₀ ℕ) R) := + toMvPowerSeries.toMulEquiv.noZeroDivisors (A := HahnSeries (σ →₀ ℕ) R) (MvPowerSeries σ R) + theorem coeff_toMvPowerSeries {f : HahnSeries (σ →₀ ℕ) R} {n : σ →₀ ℕ} : MvPowerSeries.coeff R n (toMvPowerSeries f) = f.coeff n := rfl diff --git a/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean b/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean new file mode 100644 index 0000000000000..aaab1b9cc3f6b --- /dev/null +++ b/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean @@ -0,0 +1,189 @@ +/- +Copyright (c) 2024 Antoine Chambert-Loir. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir +-/ + +import Mathlib.RingTheory.MvPowerSeries.Basic +import Mathlib.Data.Finsupp.WellFounded + +/-! LexOrder of multivariate power series + +Given an ordering of `σ` such that `WellOrderGT σ`, +the lexicographic order on `σ →₀ ℕ` is a well ordering, +which can be used to define a natural valuation `lexOrder` on the ring `MvPowerSeries σ R`: +the smallest exponent in the support. + +-/ + +namespace MvPowerSeries + +variable {σ R : Type*} +variable [Semiring R] + +section LexOrder + +open Finsupp +variable [LinearOrder σ] [WellFoundedGT σ] + +/-- The lex order on multivariate power series. -/ +noncomputable def lexOrder (φ : MvPowerSeries σ R) : (WithTop (Lex (σ →₀ ℕ))) := by + classical + exact if h : φ = 0 then ⊤ else by + have ne : Set.Nonempty (toLex '' φ.support) := by + simp only [Set.image_nonempty, Function.support_nonempty_iff, ne_eq, h, not_false_eq_true] + apply WithTop.some + apply WellFounded.min _ (toLex '' φ.support) ne + exact Finsupp.instLTLex.lt + exact wellFounded_lt + +theorem lexOrder_def_of_ne_zero {φ : MvPowerSeries σ R} (hφ : φ ≠ 0) : + ∃ (ne : Set.Nonempty (toLex '' φ.support)), + lexOrder φ = WithTop.some ((@wellFounded_lt (Lex (σ →₀ ℕ)) + (instLTLex) (Lex.wellFoundedLT)).min (toLex '' φ.support) ne) := by + suffices ne : Set.Nonempty (toLex '' φ.support) by + use ne + unfold lexOrder + simp only [dif_neg hφ] + simp only [Set.image_nonempty, Function.support_nonempty_iff, ne_eq, hφ, not_false_eq_true] + +@[simp] +theorem lexOrder_eq_top_iff_eq_zero (φ : MvPowerSeries σ R) : + lexOrder φ = ⊤ ↔ φ = 0 := by + unfold lexOrder + split_ifs with h + · simp only [h] + · simp only [h, WithTop.coe_ne_top] + +theorem lexOrder_zero : lexOrder (0 : MvPowerSeries σ R) = ⊤ := by + unfold lexOrder + rw [dif_pos rfl] + +theorem exists_finsupp_eq_lexOrder_of_ne_zero {φ : MvPowerSeries σ R} (hφ : φ ≠ 0) : + ∃ (d : σ →₀ ℕ), lexOrder φ = toLex d := by + simp only [ne_eq, ← lexOrder_eq_top_iff_eq_zero, WithTop.ne_top_iff_exists] at hφ + obtain ⟨p, hp⟩ := hφ + exact ⟨ofLex p, by simp only [toLex_ofLex, hp]⟩ + +theorem coeff_ne_zero_of_lexOrder {φ : MvPowerSeries σ R} {d : σ →₀ ℕ} + (h : toLex d = lexOrder φ) : coeff R d φ ≠ 0 := by + have hφ : φ ≠ 0 := by + simp only [ne_eq, ← lexOrder_eq_top_iff_eq_zero, ← h, WithTop.coe_ne_top, not_false_eq_true] + have hφ' := lexOrder_def_of_ne_zero hφ + rcases hφ' with ⟨ne, hφ'⟩ + simp only [← h, WithTop.coe_eq_coe] at hφ' + suffices toLex d ∈ toLex '' φ.support by + simp only [Set.mem_image_equiv, toLex_symm_eq, ofLex_toLex, Function.mem_support, ne_eq] at this + apply this + rw [hφ'] + apply WellFounded.min_mem + +theorem coeff_eq_zero_of_lt_lexOrder {φ : MvPowerSeries σ R} {d : σ →₀ ℕ} + (h : toLex d < lexOrder φ) : coeff R d φ = 0 := by + by_cases hφ : φ = 0 + · simp only [hφ, map_zero] + · rcases lexOrder_def_of_ne_zero hφ with ⟨ne, hφ'⟩ + rw [hφ', WithTop.coe_lt_coe] at h + by_contra h' + exact WellFounded.not_lt_min _ (toLex '' φ.support) ne (Set.mem_image_equiv.mpr h') h + +theorem lexOrder_le_of_coeff_ne_zero {φ : MvPowerSeries σ R} {d : σ →₀ ℕ} + (h : coeff R d φ ≠ 0) : lexOrder φ ≤ toLex d := by + rw [← not_lt] + intro h' + exact h (coeff_eq_zero_of_lt_lexOrder h') + +theorem le_lexOrder_iff {φ : MvPowerSeries σ R} {w : WithTop (Lex (σ →₀ ℕ))} : + w ≤ lexOrder φ ↔ (∀ (d : σ →₀ ℕ) (_ : toLex d < w), coeff R d φ = 0) := by + constructor + · intro h d hd + apply coeff_eq_zero_of_lt_lexOrder + exact lt_of_lt_of_le hd h + · intro h + rw [← not_lt] + intro h' + have hφ : φ ≠ 0 := by + rw [ne_eq, ← lexOrder_eq_top_iff_eq_zero] + intro h'' + rw [h'', ← not_le] at h' + apply h' + exact le_top + obtain ⟨d, hd⟩ := exists_finsupp_eq_lexOrder_of_ne_zero hφ + refine coeff_ne_zero_of_lexOrder hd.symm (h d ?_) + exact (lt_of_eq_of_lt hd.symm h') + +theorem min_lexOrder_le {φ ψ : MvPowerSeries σ R} : + min (lexOrder φ) (lexOrder ψ) ≤ lexOrder (φ + ψ) := by + rw [le_lexOrder_iff] + intro d hd + simp only [lt_min_iff] at hd + rw [map_add, coeff_eq_zero_of_lt_lexOrder hd.1, coeff_eq_zero_of_lt_lexOrder hd.2, add_zero] + +theorem coeff_mul_of_add_lexOrder {φ ψ : MvPowerSeries σ R} + {p q : σ →₀ ℕ} (hp : lexOrder φ = toLex p) (hq : lexOrder ψ = toLex q) : + coeff R (p + q) (φ * ψ) = coeff R p φ * coeff R q ψ := by + rw [coeff_mul] + apply Finset.sum_eq_single (⟨p, q⟩ : (σ →₀ ℕ) × (σ →₀ ℕ)) + · rintro ⟨u, v⟩ h h' + simp only [Finset.mem_antidiagonal] at h + simp only + by_cases hu : toLex u < toLex p + · rw [coeff_eq_zero_of_lt_lexOrder (R := R) (d := u), zero_mul] + simp only [hp, WithTop.coe_lt_coe, hu] + · rw [coeff_eq_zero_of_lt_lexOrder (d := v), mul_zero] + simp only [hq, WithTop.coe_lt_coe, ← not_le] + simp only [not_lt] at hu + intro hv + simp only [WithTop.coe_le_coe] at hv + apply h' + simp only [Prod.mk.injEq] + constructor + · apply toLex.injective + apply Or.resolve_right (eq_or_gt_of_le hu) + intro hu' + exact not_le.mpr (add_lt_add_of_lt_of_le hu' hv) (le_of_eq h) + · apply toLex.injective + apply Or.resolve_right (eq_or_gt_of_le hv) + intro hv' + exact not_le.mpr (add_lt_add_of_le_of_lt hu hv') (le_of_eq h) + · intro h + simp only [Finset.mem_antidiagonal, not_true_eq_false] at h + +theorem le_lexOrder_mul (φ ψ : MvPowerSeries σ R) : + lexOrder φ + lexOrder ψ ≤ lexOrder (φ * ψ) := by + rw [le_lexOrder_iff] + intro d hd + rw [coeff_mul] + apply Finset.sum_eq_zero + rintro ⟨u, v⟩ h + simp only [Finset.mem_antidiagonal] at h + simp only + suffices toLex u < lexOrder φ ∨ toLex v < lexOrder ψ by + rcases this with (hu | hv) + · rw [coeff_eq_zero_of_lt_lexOrder hu, zero_mul] + · rw [coeff_eq_zero_of_lt_lexOrder hv, mul_zero] + rw [or_iff_not_imp_left, not_lt, ← not_le] + intro hu hv + rw [← not_le] at hd + apply hd + simp only [← h, toLex_add, WithTop.coe_add, add_le_add hu hv] + +alias lexOrder_mul_ge := le_lexOrder_mul + +theorem lexOrder_mul [NoZeroDivisors R] (φ ψ : MvPowerSeries σ R) : + lexOrder (φ * ψ) = lexOrder φ + lexOrder ψ := by + by_cases hφ : φ = 0 + · simp only [hφ, zero_mul, lexOrder_zero, top_add] + by_cases hψ : ψ = 0 + · simp only [hψ, mul_zero, lexOrder_zero, add_top] + rcases exists_finsupp_eq_lexOrder_of_ne_zero hφ with ⟨p, hp⟩ + rcases exists_finsupp_eq_lexOrder_of_ne_zero hψ with ⟨q, hq⟩ + apply le_antisymm _ (lexOrder_mul_ge φ ψ) + rw [hp, hq] + apply lexOrder_le_of_coeff_ne_zero (d := p + q) + rw [coeff_mul_of_add_lexOrder hp hq, mul_ne_zero_iff] + exact ⟨coeff_ne_zero_of_lexOrder hp.symm, coeff_ne_zero_of_lexOrder hq.symm⟩ + +end LexOrder + +end MvPowerSeries diff --git a/Mathlib/RingTheory/MvPowerSeries/NoZeroDivisors.lean b/Mathlib/RingTheory/MvPowerSeries/NoZeroDivisors.lean index 76197b816b090..fb9d75cb2281a 100644 --- a/Mathlib/RingTheory/MvPowerSeries/NoZeroDivisors.lean +++ b/Mathlib/RingTheory/MvPowerSeries/NoZeroDivisors.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Antoine Chambert-Loir -/ -import Mathlib.RingTheory.MvPowerSeries.Basic import Mathlib.Data.Finsupp.WellFounded +import Mathlib.RingTheory.MvPowerSeries.LexOrder /-! # ZeroDivisors in a MvPowerSeries ring @@ -65,6 +65,15 @@ theorem mem_nonZeroDivisors_of_constantCoeff {φ : MvPowerSeries σ R} end Semiring +instance {σ R : Type*} [Semiring R] [NoZeroDivisors R] : + NoZeroDivisors (MvPowerSeries σ R) where + eq_zero_or_eq_zero_of_mul_eq_zero {φ ψ} h := by + letI : LinearOrder σ := LinearOrder.swap σ WellOrderingRel.isWellOrder.linearOrder + letI : WellFoundedGT σ := by + change IsWellFounded σ fun x y ↦ WellOrderingRel x y + exact IsWellOrder.toIsWellFounded + simpa only [← lexOrder_eq_top_iff_eq_zero, lexOrder_mul, WithTop.add_eq_top] using h + end MvPowerSeries end From 6b33760c50695343a2a94aa9e67dd9b84aa71868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Wed, 18 Sep 2024 22:25:32 +0000 Subject: [PATCH 031/170] chore(SetTheory/Game/Nim): redefine `grundyValue` as an infimum (#16874) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We redefine `grundyValue` as an infimum instead of using `Ordinal.mex`, and we give it a better API. This is a preliminary step before deprecating `Ordinal.mex` altogether - there's no point in using it since we can just use `Inf sᶜ` instead. --- Mathlib/SetTheory/Game/Nim.lean | 158 +++++++++++++++++++------------- 1 file changed, 94 insertions(+), 64 deletions(-) diff --git a/Mathlib/SetTheory/Game/Nim.lean b/Mathlib/SetTheory/Game/Nim.lean index 53409de60fce4..dea7c7401922c 100644 --- a/Mathlib/SetTheory/Game/Nim.lean +++ b/Mathlib/SetTheory/Game/Nim.lean @@ -206,30 +206,50 @@ theorem nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} : nim o₁ + nim o₂ ‖ 0 theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o₁ = o₂ := by rw [Impartial.equiv_iff_add_equiv_zero, nim_add_equiv_zero_iff] -/-- The Grundy value of an impartial game is recursively defined as the minimum excluded value of -the Grundy values of either its left or right options. +/-- The Grundy value of an impartial game is recursively defined as the minimum excluded value +(the infimum of the complement) of the Grundy values of either its left or right options. This is the ordinal which corresponds to the game of nim that the game is equivalent to. -/ noncomputable def grundyValue (G : PGame.{u}) : Ordinal.{u} := - Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) + sInf (Set.range fun i => grundyValue (G.moveLeft i))ᶜ termination_by G +theorem grundyValue_eq_sInf_moveLeft (G : PGame) : + grundyValue G = sInf (Set.range (grundyValue ∘ G.moveLeft))ᶜ := by + rw [grundyValue]; rfl + +@[deprecated grundyValue_eq_sInf_moveLeft (since := "2024-09-16")] theorem grundyValue_eq_mex_left (G : PGame) : - grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) := by - rw [grundyValue] + grundyValue G = Ordinal.mex fun i => grundyValue (G.moveLeft i) := + grundyValue_eq_sInf_moveLeft G -theorem grundyValue_ne_left {G : PGame} (i : G.LeftMoves) : +theorem grundyValue_ne_moveLeft {G : PGame} (i : G.LeftMoves) : grundyValue (G.moveLeft i) ≠ grundyValue G := by - conv_rhs => rw [grundyValue_eq_mex_left] - apply ne_mex _ i - -theorem exists_grundyValue_left_of_lt {G : PGame} {o : Ordinal} (h : o < grundyValue G) : + conv_rhs => rw [grundyValue_eq_sInf_moveLeft] + have := csInf_mem (nonempty_of_not_bddAbove <| + not_bddAbove_compl_of_small (Set.range fun i => grundyValue (G.moveLeft i))) + rw [Set.mem_compl_iff, Set.mem_range, not_exists] at this + exact this _ + +theorem le_grundyValue_of_Iio_subset_moveLeft {G : PGame} {o : Ordinal} + (h : Set.Iio o ⊆ Set.range (grundyValue ∘ G.moveLeft)) : o ≤ grundyValue G := by + by_contra! ho + obtain ⟨i, hi⟩ := h ho + exact grundyValue_ne_moveLeft i hi + +theorem exists_grundyValue_moveLeft_of_lt {G : PGame} {o : Ordinal} (h : o < grundyValue G) : ∃ i, grundyValue (G.moveLeft i) = o := by - rw [grundyValue_eq_mex_left] at h - exact exists_of_lt_mex h + rw [grundyValue_eq_sInf_moveLeft] at h + by_contra ha + exact h.not_le (csInf_le' ha) + +theorem grundyValue_le_of_forall_moveLeft {G : PGame} {o : Ordinal} + (h : ∀ i, grundyValue (G.moveLeft i) ≠ o) : G.grundyValue ≤ o := by + contrapose! h + exact exists_grundyValue_moveLeft_of_lt h /-- The **Sprague-Grundy theorem** states that every impartial game is equivalent to a game of nim, -namely the game of nim corresponding to the game's Grundy value -/ +namely the game of nim corresponding to the game's Grundy value. -/ theorem equiv_nim_grundyValue (G : PGame.{u}) [G.Impartial] : G ≈ nim (grundyValue G) := by rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero] intro x @@ -238,9 +258,9 @@ theorem equiv_nim_grundyValue (G : PGame.{u}) [G.Impartial] : G ≈ nim (grundyV · rw [add_moveLeft_inl, ← fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue _))), nim_add_fuzzy_zero_iff] - exact grundyValue_ne_left i + exact grundyValue_ne_moveLeft i · rw [add_moveLeft_inr, ← Impartial.exists_left_move_equiv_iff_fuzzy_zero] - obtain ⟨j, hj⟩ := exists_grundyValue_left_of_lt <| toLeftMovesNim_symm_lt i + obtain ⟨j, hj⟩ := exists_grundyValue_moveLeft_of_lt <| toLeftMovesNim_symm_lt i use toLeftMovesAdd (Sum.inl j) rw [add_moveLeft_inl, moveLeft_nim'] exact Equiv.trans (add_congr_left (equiv_nim_grundyValue _)) (hj ▸ Impartial.add_self _) @@ -274,66 +294,76 @@ theorem grundyValue_star : grundyValue star = 1 := theorem grundyValue_neg (G : PGame) [G.Impartial] : grundyValue (-G) = grundyValue G := by rw [grundyValue_eq_iff_equiv_nim, neg_equiv_iff, neg_nim, ← grundyValue_eq_iff_equiv_nim] -theorem grundyValue_eq_mex_right (G : PGame) [G.Impartial] : - grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveRight i) := by +theorem grundyValue_eq_sInf_moveRight (G : PGame) [G.Impartial] : + grundyValue G = sInf (Set.range (grundyValue ∘ G.moveRight))ᶜ := by obtain ⟨l, r, L, R⟩ := G - rw [← grundyValue_neg, grundyValue_eq_mex_left] - congr + rw [← grundyValue_neg, grundyValue_eq_sInf_moveLeft] + iterate 3 apply congr_arg ext i exact @grundyValue_neg _ (@Impartial.moveRight_impartial ⟨l, r, L, R⟩ _ _) -theorem grundyValue_ne_right {G : PGame} [G.Impartial] (i : G.RightMoves) : +@[deprecated grundyValue_eq_sInf_moveRight (since := "2024-09-16")] +theorem grundyValue_eq_mex_right (G : PGame) [G.Impartial] : + grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveRight i) := + grundyValue_eq_sInf_moveRight G + +theorem grundyValue_ne_moveRight {G : PGame} [G.Impartial] (i : G.RightMoves) : grundyValue (G.moveRight i) ≠ grundyValue G := by - conv_rhs => rw [grundyValue_eq_mex_right] - apply ne_mex _ i + convert grundyValue_ne_moveLeft (toLeftMovesNeg i) using 1 <;> simp + +theorem le_grundyValue_of_Iio_subset_moveRight {G : PGame} [G.Impartial] {o : Ordinal} + (h : Set.Iio o ⊆ Set.range (grundyValue ∘ G.moveRight)) : o ≤ grundyValue G := by + by_contra! ho + obtain ⟨i, hi⟩ := h ho + exact grundyValue_ne_moveRight i hi -theorem exists_grundyValue_right_of_lt {G : PGame} [G.Impartial] {o : Ordinal} +theorem exists_grundyValue_moveRight_of_lt {G : PGame} [G.Impartial] {o : Ordinal} (h : o < grundyValue G) : ∃ i, grundyValue (G.moveRight i) = o := by - rw [grundyValue_eq_mex_right] at h - exact exists_of_lt_mex h + rw [← grundyValue_neg] at h + obtain ⟨i, hi⟩ := exists_grundyValue_moveLeft_of_lt h + use toLeftMovesNeg.symm i + rwa [← grundyValue_neg, ← moveLeft_neg'] + +theorem grundyValue_le_of_forall_moveRight {G : PGame} [G.Impartial] {o : Ordinal} + (h : ∀ i, grundyValue (G.moveRight i) ≠ o) : G.grundyValue ≤ o := by + contrapose! h + exact exists_grundyValue_moveRight_of_lt h + +-- Todo: redefine `grundyValue` as a nimber, and prove `grundyValue (nim a + nim b) = a + b` for all +-- nimbers. --- Todo: this actually generalizes to all ordinals, by defining `Ordinal.lxor` as the pairwise --- `Nat.xor` of base `ω` Cantor normal forms. /-- The Grundy value of the sum of two nim games with natural numbers of piles equals their bitwise xor. -/ @[simp] -theorem grundyValue_nim_add_nim (n m : ℕ) : - grundyValue (nim.{u} n + nim.{u} m) = n ^^^ m := by - -- We do strong induction on both variables. - induction' n using Nat.strong_induction_on with n hn generalizing m - induction' m using Nat.strong_induction_on with m hm - rw [grundyValue_eq_mex_left] - refine (Ordinal.mex_le_of_ne.{u, u} fun i => ?_).antisymm - (Ordinal.le_mex_of_forall fun ou hu => ?_) - -- The Grundy value `n ^^^ m` can't be reached by left moves. - · apply leftMoves_add_cases i <;> - · -- A left move leaves us with a Grundy value of `k ^^^ m` for `k < n`, or - -- `n ^^^ k` for `k < m`. - refine fun a => leftMovesNimRecOn a fun ok hk => ?_ - obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _)) - simp only [add_moveLeft_inl, add_moveLeft_inr, moveLeft_nim', Equiv.symm_apply_apply] - -- The inequality follows from injectivity. - rw [natCast_lt] at hk - first - | rw [hn _ hk] - | rw [hm _ hk] - refine fun h => hk.ne ?_ - rw [Ordinal.natCast_inj] at h - first - | rwa [Nat.xor_left_inj] at h - | rwa [Nat.xor_right_inj] at h - -- Every other smaller Grundy value can be reached by left moves. - · -- If `u < m ^^^ n`, then either `u ^^^ n < m` or `u ^^^ m < n`. - obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _)) - replace hu := Ordinal.natCast_lt.1 hu - cases' Nat.lt_xor_cases hu with h h - -- In the first case, reducing the `m` pile to `u ^^^ n` gives the desired Grundy value. - · refine ⟨toLeftMovesAdd (Sum.inl <| toLeftMovesNim ⟨_, Ordinal.natCast_lt.2 h⟩), ?_⟩ - simp [Nat.xor_cancel_right, hn _ h] - -- In the second case, reducing the `n` pile to `u ^^^ m` gives the desired Grundy value. - · refine ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.natCast_lt.2 h⟩), ?_⟩ - have : n ^^^ (u ^^^ n) = u := by rw [Nat.xor_comm u, Nat.xor_cancel_left] - simpa [hm _ h] using this +theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m) = n ^^^ m := by + apply (grundyValue_le_of_forall_moveLeft _).antisymm (le_grundyValue_of_Iio_subset_moveLeft _) + -- Since XOR is injective, no left moves of `nim n + nim m` will have `n ^^^ m` as a Grundy value. + · intro i + apply leftMoves_add_cases i + all_goals + intro j + have hj := toLeftMovesNim_symm_lt j + obtain ⟨k, hk⟩ := lt_omega.1 (hj.trans (nat_lt_omega _)) + rw [hk, Nat.cast_lt] at hj + have := hj.ne + have := hj -- The termination checker doesn't work without this. + · rwa [add_moveLeft_inl, moveLeft_nim', ne_eq, hk, grundyValue_nim_add_nim, Nat.cast_inj, + Nat.xor_left_inj] + · rwa [add_moveLeft_inr, moveLeft_nim', ne_eq, hk, grundyValue_nim_add_nim, Nat.cast_inj, + Nat.xor_right_inj] + -- For any `k < n ^^^ m`, either `nim (k ^^^ m) + nim m` or `nim n + nim (k ^^^ n)` is a left + -- option with Grundy value `k`. + · intro k hk + obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _)) + rw [Set.mem_Iio, Nat.cast_lt] at hk + obtain hk | hk := Nat.lt_xor_cases hk <;> rw [← natCast_lt] at hk + · use toLeftMovesAdd (Sum.inl (toLeftMovesNim ⟨_, hk⟩)) + rw [Function.comp_apply, add_moveLeft_inl, moveLeft_nim', Equiv.symm_apply_apply, + grundyValue_nim_add_nim, Nat.xor_cancel_right] + · use toLeftMovesAdd (Sum.inr (toLeftMovesNim ⟨_, hk⟩)) + rw [Function.comp_apply, add_moveLeft_inr, moveLeft_nim', Equiv.symm_apply_apply, + grundyValue_nim_add_nim, Nat.xor_comm, Nat.xor_cancel_right] +termination_by (n, m) theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (n ^^^ m) := by rw [← grundyValue_eq_iff_equiv_nim, grundyValue_nim_add_nim] From c16a940af1cfd35a9c0a2f83bccddbc77ef3ffdd Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Thu, 19 Sep 2024 04:26:50 +0000 Subject: [PATCH 032/170] feat: closures of convex sets in locally convex spaces with the same continuous linear functionals (#16859) --- Mathlib.lean | 1 + Mathlib/Analysis/LocallyConvex/WeakSpace.lean | 100 ++++++++++++++++++ .../Topology/Algebra/Module/WeakBilin.lean | 8 +- Mathlib/Topology/Algebra/Module/WeakDual.lean | 79 +++++++++++--- 4 files changed, 168 insertions(+), 20 deletions(-) create mode 100644 Mathlib/Analysis/LocallyConvex/WeakSpace.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9dc2fa945abee..925312093dff7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1175,6 +1175,7 @@ import Mathlib.Analysis.LocallyConvex.ContinuousOfBounded import Mathlib.Analysis.LocallyConvex.Polar import Mathlib.Analysis.LocallyConvex.StrongTopology import Mathlib.Analysis.LocallyConvex.WeakDual +import Mathlib.Analysis.LocallyConvex.WeakSpace import Mathlib.Analysis.LocallyConvex.WithSeminorms import Mathlib.Analysis.Matrix import Mathlib.Analysis.MeanInequalities diff --git a/Mathlib/Analysis/LocallyConvex/WeakSpace.lean b/Mathlib/Analysis/LocallyConvex/WeakSpace.lean new file mode 100644 index 0000000000000..ff4823a65b3fb --- /dev/null +++ b/Mathlib/Analysis/LocallyConvex/WeakSpace.lean @@ -0,0 +1,100 @@ +/- +Copyright (c) 2024 Jireh Loreaux. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jireh Loreaux +-/ +import Mathlib.LinearAlgebra.Dual +import Mathlib.Analysis.NormedSpace.HahnBanach.Separation +import Mathlib.Topology.Algebra.Module.WeakDual + +/-! # Closures of convex sets in locally convex spaces + +This file contains the standard result that if `E` is a vector space with two locally convex +topologies, then the closure of a convex set is the same in either topology, provided they have the +same collection of continuous linear functionals. In particular, the weak closure of a convex set +in a locally convex space coincides with the closure in the original topology. +Of course, we phrase this in terms of linear maps between locally convex spaces, rather than +creating two separate topologies on the same space. +-/ + +variable {𝕜 E F : Type*} +variable [RCLike 𝕜] [AddCommGroup E] [Module 𝕜 E] [AddCommGroup F] [Module 𝕜 F] +variable [Module ℝ E] [IsScalarTower ℝ 𝕜 E] [Module ℝ F] [IsScalarTower ℝ 𝕜 F] +variable [TopologicalSpace E] [TopologicalAddGroup E] [ContinuousSMul 𝕜 E] [LocallyConvexSpace ℝ E] +variable [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousSMul 𝕜 F] [LocallyConvexSpace ℝ F] + +variable (𝕜) in +/-- If `E` is a locally convex space over `𝕜` (with `RCLike 𝕜`), and `s : Set E` is `ℝ`-convex, then +the closure of `s` and the weak closure of `s` coincide. More precisely, the topological closure +commutes with `toWeakSpace 𝕜 E`. + +This holds more generally for any linear equivalence `e : E ≃ₗ[𝕜] F` between locally convex spaces +such that precomposition with `e` and `e.symm` preserves continuity of linear functionals. See +`LinearEquiv.image_closure_of_convex`. -/ +theorem Convex.toWeakSpace_closure {s : Set E} (hs : Convex ℝ s) : + (toWeakSpace 𝕜 E) '' (closure s) = closure (toWeakSpace 𝕜 E '' s) := by + refine le_antisymm (map_continuous <| toWeakSpaceCLM 𝕜 E).continuousOn.image_closure + (Set.compl_subset_compl.mp fun x hx ↦ ?_) + obtain ⟨x, -, rfl⟩ := (toWeakSpace 𝕜 E).toEquiv.image_compl (closure s) |>.symm.subset hx + have : ContinuousSMul ℝ E := IsScalarTower.continuousSMul 𝕜 + obtain ⟨f, u, hus, hux⟩ := RCLike.geometric_hahn_banach_closed_point (𝕜 := 𝕜) + hs.closure isClosed_closure (by simpa using hx) + let f' : WeakSpace 𝕜 E →L[𝕜] 𝕜 := + { toLinearMap := (f : E →ₗ[𝕜] 𝕜).comp ((toWeakSpace 𝕜 E).symm : WeakSpace 𝕜 E →ₗ[𝕜] E) + cont := WeakBilin.eval_continuous (topDualPairing 𝕜 E).flip _ } + have hux' : u < RCLike.reCLM.comp (f'.restrictScalars ℝ) (toWeakSpace 𝕜 E x) := by simpa [f'] + have hus' : closure (toWeakSpace 𝕜 E '' s) ⊆ + {y | RCLike.reCLM.comp (f'.restrictScalars ℝ) y ≤ u} := by + refine closure_minimal ?_ <| isClosed_le (by fun_prop) (by fun_prop) + rintro - ⟨y, hy, rfl⟩ + simpa [f'] using (hus y <| subset_closure hy).le + exact (hux'.not_le <| hus' ·) + +/-- If `e : E →ₗ[𝕜] F` is a linear map between locally convex spaces, and `f ∘ e` is continuous +for every continuous linear functional `f : F →L[𝕜] 𝕜`, then `e` commutes with the closure on +convex sets. -/ +theorem LinearMap.image_closure_of_convex {s : Set E} (hs : Convex ℝ s) (e : E →ₗ[𝕜] F) + (he : ∀ f : F →L[𝕜] 𝕜, Continuous (e.dualMap f)) : + e '' (closure s) ⊆ closure (e '' s) := by + suffices he' : Continuous (toWeakSpace 𝕜 F <| e <| (toWeakSpace 𝕜 E).symm ·) by + have h_convex : Convex ℝ (e '' s) := hs.linear_image e + rw [← Set.image_subset_image_iff (toWeakSpace 𝕜 F).injective, h_convex.toWeakSpace_closure 𝕜] + simpa only [Set.image_image, ← hs.toWeakSpace_closure 𝕜, LinearEquiv.symm_apply_apply] + using he'.continuousOn.image_closure (s := toWeakSpace 𝕜 E '' s) + exact WeakBilin.continuous_of_continuous_eval _ fun f ↦ + WeakBilin.eval_continuous _ { toLinearMap := e.dualMap f : E →L[𝕜] 𝕜 } + +/-- If `e` is a linear isomorphism between two locally convex spaces, and `e` induces (via +precomposition) an isomorphism between their continuous duals, then `e` commutes with the closure +on convex sets. + +The hypotheses hold automatically for `e := toWeakSpace 𝕜 E`, see `Convex.toWeakSpace_closure`. -/ +theorem LinearEquiv.image_closure_of_convex {s : Set E} (hs : Convex ℝ s) (e : E ≃ₗ[𝕜] F) + (he₁ : ∀ f : F →L[𝕜] 𝕜, Continuous (e.dualMap f)) + (he₂ : ∀ f : E →L[𝕜] 𝕜, Continuous (e.symm.dualMap f)) : + e '' (closure s) = closure (e '' s) := by + refine le_antisymm ((e : E →ₗ[𝕜] F).image_closure_of_convex hs he₁) ?_ + simp only [Set.le_eq_subset, ← Set.image_subset_image_iff e.symm.injective] + simpa [Set.image_image] + using (e.symm : F →ₗ[𝕜] E).image_closure_of_convex (hs.linear_image (e : E →ₗ[𝕜] F)) he₂ + +/-- If `e` is a linear isomorphism between two locally convex spaces, and `e` induces (via +precomposition) an isomorphism between their continuous duals, then `e` commutes with the closure +on convex sets. + +The hypotheses hold automatically for `e := toWeakSpace 𝕜 E`, see `Convex.toWeakSpace_closure`. -/ +theorem LinearEquiv.image_closure_of_convex' {s : Set E} (hs : Convex ℝ s) (e : E ≃ₗ[𝕜] F) + (e_dual : (F →L[𝕜] 𝕜) ≃ (E →L[𝕜] 𝕜)) + (he : ∀ f : F →L[𝕜] 𝕜, (e_dual f : E →ₗ[𝕜] 𝕜) = e.dualMap f) : + e '' (closure s) = closure (e '' s) := by + have he' (f : E →L[𝕜] 𝕜) : (e_dual.symm f : F →ₗ[𝕜] 𝕜) = e.symm.dualMap f := by + simp only [DFunLike.ext'_iff, ContinuousLinearMap.coe_coe] at he ⊢ + have (g : E →L[𝕜] 𝕜) : ⇑g = e_dual.symm g ∘ e := by + have := he _ ▸ congr(⇑$(e_dual.apply_symm_apply g)).symm + simpa + ext x + conv_rhs => rw [LinearEquiv.dualMap_apply, ContinuousLinearMap.coe_coe, this] + simp + refine e.image_closure_of_convex hs ?_ ?_ + · simpa [← he] using fun f ↦ map_continuous (e_dual f) + · simpa [← he'] using fun f ↦ map_continuous (e_dual.symm f) diff --git a/Mathlib/Topology/Algebra/Module/WeakBilin.lean b/Mathlib/Topology/Algebra/Module/WeakBilin.lean index ce7fa45066790..916301730f678 100644 --- a/Mathlib/Topology/Algebra/Module/WeakBilin.lean +++ b/Mathlib/Topology/Algebra/Module/WeakBilin.lean @@ -76,12 +76,12 @@ instance instModule [CommSemiring 𝕜] [AddCommMonoid E] [m : Module 𝕜 E] [A instance instAddCommGroup [CommSemiring 𝕜] [a : AddCommGroup E] [Module 𝕜 E] [AddCommMonoid F] [Module 𝕜 F] (B : E →ₗ[𝕜] F →ₗ[𝕜] 𝕜) : AddCommGroup (WeakBilin B) := a -instance (priority := 100) instModule' [CommSemiring 𝕜] [CommSemiring 𝕝] [AddCommGroup E] - [Module 𝕜 E] [AddCommGroup F] [Module 𝕜 F] [m : Module 𝕝 E] (B : E →ₗ[𝕜] F →ₗ[𝕜] 𝕜) : +instance (priority := 100) instModule' [CommSemiring 𝕜] [CommSemiring 𝕝] [AddCommMonoid E] + [Module 𝕜 E] [AddCommMonoid F] [Module 𝕜 F] [m : Module 𝕝 E] (B : E →ₗ[𝕜] F →ₗ[𝕜] 𝕜) : Module 𝕝 (WeakBilin B) := m -instance instIsScalarTower [CommSemiring 𝕜] [CommSemiring 𝕝] [AddCommGroup E] [Module 𝕜 E] - [AddCommGroup F] [Module 𝕜 F] [SMul 𝕝 𝕜] [Module 𝕝 E] [s : IsScalarTower 𝕝 𝕜 E] +instance instIsScalarTower [CommSemiring 𝕜] [CommSemiring 𝕝] [AddCommMonoid E] [Module 𝕜 E] + [AddCommMonoid F] [Module 𝕜 F] [SMul 𝕝 𝕜] [Module 𝕝 E] [s : IsScalarTower 𝕝 𝕜 E] (B : E →ₗ[𝕜] F →ₗ[𝕜] 𝕜) : IsScalarTower 𝕝 𝕜 (WeakBilin B) := s section Semiring diff --git a/Mathlib/Topology/Algebra/Module/WeakDual.lean b/Mathlib/Topology/Algebra/Module/WeakDual.lean index 0085b9b75d5bd..1a71efa833d83 100644 --- a/Mathlib/Topology/Algebra/Module/WeakDual.lean +++ b/Mathlib/Topology/Algebra/Module/WeakDual.lean @@ -54,20 +54,16 @@ open Filter open Topology -variable {α 𝕜 E F : Type*} - -section WeakStarTopology +variable {α 𝕜 𝕝 E F : Type*} /-- The canonical pairing of a vector space and its topological dual. -/ def topDualPairing (𝕜 E) [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAdd 𝕜] [AddCommMonoid E] [Module 𝕜 E] [TopologicalSpace E] [ContinuousConstSMul 𝕜 𝕜] : (E →L[𝕜] 𝕜) →ₗ[𝕜] E →ₗ[𝕜] 𝕜 := ContinuousLinearMap.coeLM 𝕜 -variable [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAdd 𝕜] -variable [ContinuousConstSMul 𝕜 𝕜] -variable [AddCommMonoid E] [Module 𝕜 E] [TopologicalSpace E] - -theorem topDualPairing_apply (v : E →L[𝕜] 𝕜) (x : E) : topDualPairing 𝕜 E v x = v x := +theorem topDualPairing_apply [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAdd 𝕜] + [AddCommMonoid E] [Module 𝕜 E] [TopologicalSpace E] [ContinuousConstSMul 𝕜 𝕜] (v : E →L[𝕜] 𝕜) + (x : E) : topDualPairing 𝕜 E v x = v x := rfl /-- The weak star topology is the topology coarsest topology on `E →L[𝕜] 𝕜` such that all @@ -78,6 +74,12 @@ def WeakDual (𝕜 E : Type*) [CommSemiring 𝕜] [TopologicalSpace 𝕜] [Conti namespace WeakDual +section Semiring + +variable [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAdd 𝕜] +variable [ContinuousConstSMul 𝕜 𝕜] +variable [AddCommMonoid E] [Module 𝕜 E] [TopologicalSpace E] + -- Porting note: the next four instances should be derived from the definition instance instAddCommMonoid : AddCommMonoid (WeakDual 𝕜 E) := WeakBilin.instAddCommMonoid (topDualPairing 𝕜 E) @@ -150,6 +152,21 @@ instance instT2Space [T2Space 𝕜] : T2Space (WeakDual 𝕜 E) := WeakBilin.embedding <| show Function.Injective (topDualPairing 𝕜 E) from ContinuousLinearMap.coe_injective +end Semiring + +section Ring + +variable [CommRing 𝕜] [TopologicalSpace 𝕜] [TopologicalAddGroup 𝕜] [ContinuousConstSMul 𝕜 𝕜] +variable [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] [TopologicalAddGroup E] + +instance instAddCommGroup : AddCommGroup (WeakDual 𝕜 E) := + WeakBilin.instAddCommGroup (topDualPairing 𝕜 E) + +instance instTopologicalAddGroup : TopologicalAddGroup (WeakDual 𝕜 E) := + WeakBilin.instTopologicalAddGroup (topDualPairing 𝕜 E) + +end Ring + end WeakDual /-- The weak topology is the topology coarsest topology on `E` such that all functionals @@ -158,6 +175,12 @@ def WeakSpace (𝕜 E) [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAd [ContinuousConstSMul 𝕜 𝕜] [AddCommMonoid E] [Module 𝕜 E] [TopologicalSpace E] := WeakBilin (topDualPairing 𝕜 E).flip +section Semiring + +variable [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAdd 𝕜] +variable [ContinuousConstSMul 𝕜 𝕜] +variable [AddCommMonoid E] [Module 𝕜 E] [TopologicalSpace E] + namespace WeakSpace -- Porting note: the next four instances should be derived from the definition @@ -173,6 +196,13 @@ instance instTopologicalSpace : TopologicalSpace (WeakSpace 𝕜 E) := instance instContinuousAdd : ContinuousAdd (WeakSpace 𝕜 E) := WeakBilin.instContinuousAdd (topDualPairing 𝕜 E).flip +instance instModule' [CommSemiring 𝕝] [Module 𝕝 E] : Module 𝕝 (WeakSpace 𝕜 E) := + WeakBilin.instModule' (topDualPairing 𝕜 E).flip + +instance instIsScalarTower [CommSemiring 𝕝] [Module 𝕝 𝕜] [Module 𝕝 E] [IsScalarTower 𝕝 𝕜 E] : + IsScalarTower 𝕝 𝕜 (WeakSpace 𝕜 E) := + WeakBilin.instIsScalarTower (topDualPairing 𝕜 E).flip + variable [AddCommMonoid F] [Module 𝕜 F] [TopologicalSpace F] /-- A continuous linear map from `E` to `F` is still continuous when `E` and `F` are equipped with @@ -199,7 +229,7 @@ def toWeakSpace : E ≃ₗ[𝕜] WeakSpace 𝕜 E := LinearEquiv.refl 𝕜 E variable (𝕜 E) in /-- For a topological vector space `E`, "identity mapping" `E → WeakSpace 𝕜 E` is continuous. This definition implements it as a continuous linear map. -/ -def continuousLinearMapToWeakSpace : E →L[𝕜] WeakSpace 𝕜 E where +def toWeakSpaceCLM : E →L[𝕜] WeakSpace 𝕜 E where __ := toWeakSpace 𝕜 E cont := by apply WeakBilin.continuous_of_continuous_eval @@ -207,21 +237,21 @@ def continuousLinearMapToWeakSpace : E →L[𝕜] WeakSpace 𝕜 E where variable (𝕜 E) in @[simp] -theorem continuousLinearMapToWeakSpace_eq_toWeakSpace (x : E) : - continuousLinearMapToWeakSpace 𝕜 E x = toWeakSpace 𝕜 E x := by rfl +theorem toWeakSpaceCLM_eq_toWeakSpace (x : E) : + toWeakSpaceCLM 𝕜 E x = toWeakSpace 𝕜 E x := by rfl -theorem continuousLinearMapToWeakSpace_bijective : - Function.Bijective (continuousLinearMapToWeakSpace 𝕜 E) := +theorem toWeakSpaceCLM_bijective : + Function.Bijective (toWeakSpaceCLM 𝕜 E) := (toWeakSpace 𝕜 E).bijective /-- The canonical map from `WeakSpace 𝕜 E` to `E` is an open map. -/ theorem isOpenMap_toWeakSpace_symm : IsOpenMap (toWeakSpace 𝕜 E).symm := - IsOpenMap.of_inverse (continuousLinearMapToWeakSpace 𝕜 E).cont + IsOpenMap.of_inverse (toWeakSpaceCLM 𝕜 E).cont (toWeakSpace 𝕜 E).left_inv (toWeakSpace 𝕜 E).right_inv /-- A set in `E` which is open in the weak topology is open. -/ theorem WeakSpace.isOpen_of_isOpen (V : Set E) - (hV : IsOpen ((continuousLinearMapToWeakSpace 𝕜 E) '' V : Set (WeakSpace 𝕜 E))) : IsOpen V := by + (hV : IsOpen ((toWeakSpaceCLM 𝕜 E) '' V : Set (WeakSpace 𝕜 E))) : IsOpen V := by simpa [Set.image_image] using isOpenMap_toWeakSpace_symm _ hV theorem tendsto_iff_forall_eval_tendsto_topDualPairing {l : Filter α} {f : α → WeakDual 𝕜 E} @@ -230,4 +260,21 @@ theorem tendsto_iff_forall_eval_tendsto_topDualPairing {l : Filter α} {f : α ∀ y, Tendsto (fun i => topDualPairing 𝕜 E (f i) y) l (𝓝 (topDualPairing 𝕜 E x y)) := WeakBilin.tendsto_iff_forall_eval_tendsto _ ContinuousLinearMap.coe_injective -end WeakStarTopology +end Semiring + +section Ring + +namespace WeakSpace + +variable [CommRing 𝕜] [TopologicalSpace 𝕜] [TopologicalAddGroup 𝕜] [ContinuousConstSMul 𝕜 𝕜] +variable [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] [TopologicalAddGroup E] + +instance instAddCommGroup : AddCommGroup (WeakSpace 𝕜 E) := + WeakBilin.instAddCommGroup (topDualPairing 𝕜 E).flip + +instance instTopologicalAddGroup : TopologicalAddGroup (WeakSpace 𝕜 E) := + WeakBilin.instTopologicalAddGroup (topDualPairing 𝕜 E).flip + +end WeakSpace + +end Ring From f2c6dd5e664931cac7e67308425179ff12b9c568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 19 Sep 2024 05:29:40 +0000 Subject: [PATCH 033/170] doc(Order/SuccPred/Limit): update comments (#16901) --- Mathlib/Order/SuccPred/Limit.lean | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Mathlib/Order/SuccPred/Limit.lean b/Mathlib/Order/SuccPred/Limit.lean index 2309332275f98..dd876c6f2254d 100644 --- a/Mathlib/Order/SuccPred/Limit.lean +++ b/Mathlib/Order/SuccPred/Limit.lean @@ -42,8 +42,7 @@ variable [LT α] It's so named because in a successor order, a successor pre-limit can't be the successor of anything smaller. -For some applications, it's desirable to exclude the case where an element is minimal. A future PR -will introduce `IsSuccLimit` for this usage. -/ +Use `IsSuccLimit` if you want to exclude the case of a minimal element. -/ def IsSuccPrelimit (a : α) : Prop := ∀ b, ¬b ⋖ a @@ -302,8 +301,7 @@ variable [LT α] {a : α} It's so named because in a predecessor order, a predecessor pre-limit can't be the predecessor of anything smaller. -For some applications, it's desirable to exclude maximal elements from this definition. For that, -see `IsPredLimit`. -/ +Use `IsPredLimit` to exclude the case of a maximal element. -/ def IsPredPrelimit (a : α) : Prop := ∀ b, ¬ a ⋖ b From 46c490a61e979ba0754250e5806bf083a9657ffc Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 19 Sep 2024 06:45:48 +0000 Subject: [PATCH 034/170] chore: bump Mathlib dependencies (#16934) --- Mathlib/Data/String/Basic.lean | 1 + Mathlib/Tactic/Bound/Attribute.lean | 1 + lake-manifest.json | 4 ++-- test/propose.lean | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Mathlib/Data/String/Basic.lean b/Mathlib/Data/String/Basic.lean index 99c98349ad745..d30479b15e611 100644 --- a/Mathlib/Data/String/Basic.lean +++ b/Mathlib/Data/String/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Batteries.Data.String.Lemmas import Mathlib.Data.List.Lex import Mathlib.Data.Char import Mathlib.Tactic.AdaptationNote diff --git a/Mathlib/Tactic/Bound/Attribute.lean b/Mathlib/Tactic/Bound/Attribute.lean index a33e962df9870..83685e229820e 100644 --- a/Mathlib/Tactic/Bound/Attribute.lean +++ b/Mathlib/Tactic/Bound/Attribute.lean @@ -6,6 +6,7 @@ Authors: Geoffrey Irving import Mathlib.Algebra.Group.ZeroOne import Mathlib.Tactic.Bound.Init import Qq +import Aesop /-! # The `bound` attribute diff --git a/lake-manifest.json b/lake-manifest.json index 21d9737992048..61c218e567c74 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -25,7 +25,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "2c39748d927749624f480b641f1d2d77b8632b92", + "rev": "61fb4d1a2a6a4fe4be260ca31c58af1234ff298b", "name": "aesop", "manifestFile": "lake-manifest.json", "inputRev": "master", @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "3e9460c40e09457b2fd079ef55316535536425fc", + "rev": "565ce2c97c20428195f8e7861cc0fb1f537e4d25", "name": "LeanSearchClient", "manifestFile": "lake-manifest.json", "inputRev": "main", diff --git a/test/propose.lean b/test/propose.lean index 99c6ece1d4e46..04d97bb804156 100644 --- a/test/propose.lean +++ b/test/propose.lean @@ -2,6 +2,7 @@ import Mathlib.Tactic.Propose import Mathlib.Tactic.GuardHypNums import Mathlib.Algebra.Associated.Basic import Mathlib.Data.Set.Subsingleton +import Batteries.Data.List.Lemmas -- For debugging, you may find these options useful: -- set_option trace.Tactic.propose true From 1552fec0a2219818167af648423634288e468482 Mon Sep 17 00:00:00 2001 From: Etienne Date: Thu, 19 Sep 2024 07:48:53 +0000 Subject: [PATCH 035/170] feat: generalize `Set.restrict_apply` to dependent functions (#16928) Generalize `Set.restrict_apply` to dependent functions. --- Mathlib/Data/Set/Function.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index 99367bed783cb..e421706c65305 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -50,7 +50,7 @@ theorem restrict_eq (f : α → β) (s : Set α) : s.restrict f = f ∘ Subtype. rfl @[simp] -theorem restrict_apply (f : α → β) (s : Set α) (x : s) : s.restrict f x = f x := +theorem restrict_apply (f : (a : α) → π a) (s : Set α) (x : s) : s.restrict f x = f x := rfl theorem restrict_eq_iff {f : ∀ a, π a} {s : Set α} {g : ∀ a : s, π a} : From 9ba85757caa00141c2d788d0a8a1ab53da6302d8 Mon Sep 17 00:00:00 2001 From: Jiang Jiedong <107380768+jjdishere@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:44:20 +0000 Subject: [PATCH 036/170] feat(FieldTheory/Separable): Add lemmas of elementwise `IsSeparable` (#14404) Add lemmas of elementwise `IsSeparable` decomposed from `Algebra.IsSeparable` lemmas. Add `Field.isSeparable_neg`, `Field.isSeparable_sub` Co-authored-by: jjdishere Co-authored-by: Filippo A. E. Nuccio --- Mathlib/FieldTheory/PurelyInseparable.lean | 4 +- Mathlib/FieldTheory/Separable.lean | 168 +++++++++++++++------ Mathlib/FieldTheory/SeparableClosure.lean | 7 +- Mathlib/FieldTheory/SeparableDegree.lean | 17 ++- 4 files changed, 140 insertions(+), 56 deletions(-) diff --git a/Mathlib/FieldTheory/PurelyInseparable.lean b/Mathlib/FieldTheory/PurelyInseparable.lean index abf7d16a7a678..f8b347c9bf68a 100644 --- a/Mathlib/FieldTheory/PurelyInseparable.lean +++ b/Mathlib/FieldTheory/PurelyInseparable.lean @@ -604,7 +604,7 @@ if `E` is purely inseparable over it. -/ theorem separableClosure_le (L : IntermediateField F E) [h : IsPurelyInseparable L E] : separableClosure F E ≤ L := fun x hx ↦ by obtain ⟨y, rfl⟩ := h.inseparable' _ <| - IsSeparable.of_isScalarTower L (mem_separableClosure_iff.1 hx) + IsSeparable.tower_top L (mem_separableClosure_iff.1 hx) exact y.2 /-- If `E / F` is algebraic, then an intermediate field of `E / F` contains the @@ -1071,7 +1071,7 @@ theorem minpoly.map_eq_of_isSeparable_of_isPurelyInseparable (x : K) have hi' : IsIntegral E x := IsIntegral.tower_top hi refine eq_of_monic_of_dvd_of_natDegree_le (monic hi') ((monic hi).map (algebraMap F E)) (dvd_map_of_isScalarTower F E x) (le_of_eq ?_) - have hsep' := IsSeparable.of_isScalarTower E hsep + have hsep' := IsSeparable.tower_top E hsep haveI := (isSeparable_adjoin_simple_iff_isSeparable _ _).2 hsep haveI := (isSeparable_adjoin_simple_iff_isSeparable _ _).2 hsep' have := Algebra.IsSeparable.isAlgebraic F F⟮x⟯ diff --git a/Mathlib/FieldTheory/Separable.lean b/Mathlib/FieldTheory/Separable.lean index e02a32044e880..c6a87d0dbf1fb 100644 --- a/Mathlib/FieldTheory/Separable.lean +++ b/Mathlib/FieldTheory/Separable.lean @@ -22,7 +22,7 @@ properties about separable polynomials here. * `IsSeparable K x`: an element `x` is separable over `K` iff the minimal polynomial of `x` over `K` is separable. * `Algebra.IsSeparable K L`: `L` is separable over `K` iff every element in `L` is separable -over `K` +over `K`. -/ @@ -503,7 +503,7 @@ open Polynomial section CommRing -variable (F K : Type*) [CommRing F] [Ring K] [Algebra F K] +variable (F L K : Type*) [CommRing F] [Ring K] [Algebra F K] -- TODO: refactor to allow transcendental extensions? -- See: https://en.wikipedia.org/wiki/Separable_extension#Separability_of_transcendental_extensions @@ -514,7 +514,7 @@ variable (F K : Type*) [CommRing F] [Ring K] [Algebra F K] variable {K} in /-- An element `x` of an algebra `K` over a commutative ring `F` is said to be *separable*, if its -minimal polynamial over `K` is separable. Note that the minimal polynomial of any element not +minimal polynomial over `K` is separable. Note that the minimal polynomial of any element not integral over `F` is defined to be `0`, which is not a separable polynomial. -/ def IsSeparable (x : K) : Prop := Polynomial.Separable (minpoly F x) @@ -547,6 +547,11 @@ theorem IsSeparable.isIntegral {x : K} (h : IsSeparable F x) : IsIntegral F x := theorem Algebra.IsSeparable.isIntegral [Algebra.IsSeparable F K] : ∀ x : K, IsIntegral F x := fun x ↦ _root_.IsSeparable.isIntegral (Algebra.IsSeparable.isSeparable F x) +variable (K) in +instance Algebra.IsSeparable.isAlgebraic [Nontrivial F] [Algebra.IsSeparable F K] : + Algebra.IsAlgebraic F K := + ⟨fun x ↦ (Algebra.IsSeparable.isIntegral F x).isAlgebraic⟩ + variable {F} theorem Algebra.isSeparable_iff : @@ -554,72 +559,132 @@ theorem Algebra.isSeparable_iff : ⟨fun _ x => ⟨Algebra.IsSeparable.isIntegral F x, Algebra.IsSeparable.isSeparable F x⟩, fun h => ⟨fun x => (h x).2⟩⟩ -variable {E : Type*} [Ring E] [Algebra F E] (e : K ≃ₐ[F] E) +variable {E : Type*} + +section AlgEquiv + +variable [Ring E] [Algebra F E] (e : K ≃ₐ[F] E) include e +/-- Transfer `IsSeparable` across an `AlgEquiv`. -/ +theorem AlgEquiv.isSeparable_iff {x : K} : IsSeparable F (e x) ↔ IsSeparable F x := by + simp only [IsSeparable, minpoly.algEquiv_eq e x] + /-- Transfer `Algebra.IsSeparable` across an `AlgEquiv`. -/ -theorem AlgEquiv.isSeparable [Algebra.IsSeparable F K] : Algebra.IsSeparable F E := - ⟨fun _ ↦ - by rw [IsSeparable, ← minpoly.algEquiv_eq e.symm]; exact Algebra.IsSeparable.isSeparable F _⟩ +theorem AlgEquiv.Algebra.isSeparable [Algebra.IsSeparable F K] : Algebra.IsSeparable F E := + ⟨fun _ ↦ e.symm.isSeparable_iff.mp (Algebra.IsSeparable.isSeparable _ _)⟩ -theorem AlgEquiv.isSeparable_iff : Algebra.IsSeparable F K ↔ Algebra.IsSeparable F E := - ⟨fun _ ↦ e.isSeparable, fun _ ↦ e.symm.isSeparable⟩ +@[deprecated (since := "2024-08-06")] +alias AlgEquiv.isSeparable := AlgEquiv.Algebra.isSeparable -variable (F K) +theorem AlgEquiv.Algebra.isSeparable_iff : Algebra.IsSeparable F K ↔ Algebra.IsSeparable F E := + ⟨fun _ ↦ AlgEquiv.Algebra.isSeparable e, fun _ ↦ AlgEquiv.Algebra.isSeparable e.symm⟩ -instance Algebra.IsSeparable.isAlgebraic [Nontrivial F] [Algebra.IsSeparable F K] : - Algebra.IsAlgebraic F K := - ⟨fun x ↦ (Algebra.IsSeparable.isIntegral F x).isAlgebraic⟩ +end AlgEquiv + +section IsScalarTower + +variable [Field L] [CommRing E] [Algebra F L] + [Algebra F E] [Algebra L E] [IsScalarTower F L E] + +/-- If `E / L / F` is a scalar tower and `x : E` is separable over `F`, then it's also separable +over `L`. -/ +theorem IsSeparable.tower_top + {x : E} (h : IsSeparable F x) : IsSeparable L x := + h.map.of_dvd (minpoly.dvd_map_of_isScalarTower _ _ _) + +variable (F E) in +theorem Algebra.isSeparable_tower_top_of_isSeparable [Algebra.IsSeparable F E] : + Algebra.IsSeparable L E := + ⟨fun x ↦ IsSeparable.tower_top _ (Algebra.IsSeparable.isSeparable F x)⟩ + +@[deprecated (since := "2024-08-06")] +alias IsSeparable.of_isScalarTower := Algebra.isSeparable_tower_top_of_isSeparable + +end IsScalarTower end CommRing -instance Algebra.isSeparable_self (F : Type*) [Field F] : Algebra.IsSeparable F F := - ⟨fun x => by - rw [IsSeparable, minpoly.eq_X_sub_C'] - exact separable_X_sub_C⟩ +section Field + +variable (F : Type*) [Field F] {K E E' : Type*} + +section IsIntegral + +variable [Ring K] [Algebra F K] + +variable {F} in +theorem isSeparable_algebraMap (x : F) : IsSeparable F (algebraMap F K x) := + Polynomial.Separable.of_dvd (Polynomial.separable_X_sub_C (x := x)) + (minpoly.dvd F (algebraMap F K x) (by simp only [map_sub, aeval_X, aeval_C, sub_self])) + +instance Algebra.isSeparable_self : Algebra.IsSeparable F F := + ⟨isSeparable_algebraMap⟩ + +variable [IsDomain K] [Algebra.IsIntegral F K] [CharZero F] + +theorem IsSeparable.of_integral (x : K) : IsSeparable F x := + (minpoly.irreducible <| Algebra.IsIntegral.isIntegral x).separable -- See note [lower instance priority] -/-- An integral extension in characteristic 0 is separable. -/ -instance (priority := 100) Algebra.IsSeparable.of_integral (F K : Type*) [Field F] [Ring K] - [IsDomain K] [Algebra F K] [Algebra.IsIntegral F K] [CharZero F] : Algebra.IsSeparable F K := - ⟨fun x => (minpoly.irreducible <| Algebra.IsIntegral.isIntegral x).separable⟩ - -section IsSeparableTower - -/-- If `R / K / A` is an extension tower, `x : R` is separable over `A`, then it's also separable -over `K`. -/ -theorem IsSeparable.of_isScalarTower {A : Type*} [CommRing A] - (K : Type*) [Field K] [Algebra A K] {R : Type*} [CommRing R] [Algebra A R] [Algebra K R] - [IsScalarTower A K R] {x : R} (h : IsSeparable A x) : IsSeparable K x := - h.map.of_dvd (minpoly.dvd_map_of_isScalarTower _ _ _) +variable (K) in +/-- A integral field extension in characteristic 0 is separable. -/ +protected instance (priority := 100) Algebra.IsSeparable.of_integral : Algebra.IsSeparable F K := + ⟨_root_.IsSeparable.of_integral _⟩ -variable (F K E : Type*) [Field F] [Field K] [Field E] [Algebra F K] [Algebra F E] [Algebra K E] - [IsScalarTower F K E] +end IsIntegral -theorem Algebra.isSeparable_tower_top_of_isSeparable [Algebra.IsSeparable F E] : - Algebra.IsSeparable K E := - ⟨fun x ↦ IsSeparable.of_isScalarTower _ (Algebra.IsSeparable.isSeparable F x)⟩ +section IsScalarTower -theorem Algebra.isSeparable_tower_bot_of_isSeparable [h : Algebra.IsSeparable F E] : - Algebra.IsSeparable F K := - ⟨fun x ↦ +variable [Field K] [Ring E] [Algebra F K] [Algebra F E] [Algebra K E] + [Nontrivial E] [IsScalarTower F K E] + +variable {F} in +/-- If `E / K / F` is a scalar tower and `algebraMap K E x` is separable over `F`, then `x` is +`` +also separable over `F`. -/ +theorem IsSeparable.tower_bot {x : K} (h : IsSeparable F (algebraMap K E x)) : IsSeparable F x := have ⟨_q, hq⟩ := minpoly.dvd F x ((aeval_algebraMap_eq_zero_iff _ _ _).mp (minpoly.aeval F ((algebraMap K E) x))) - (Eq.mp (congrArg Separable hq) (h.isSeparable _)).of_mul_left⟩ + (Eq.mp (congrArg Separable hq) h).of_mul_left + +variable (K E) in +theorem Algebra.isSeparable_tower_bot_of_isSeparable [h : Algebra.IsSeparable F E] : + Algebra.IsSeparable F K := + ⟨fun _ ↦ IsSeparable.tower_bot (h.isSeparable _)⟩ -variable {E} +end IsScalarTower -theorem Algebra.IsSeparable.of_algHom (E' : Type*) [Field E'] [Algebra F E'] (f : E →ₐ[F] E') - [Algebra.IsSeparable F E'] : Algebra.IsSeparable F E := by - letI : Algebra E E' := RingHom.toAlgebra f.toRingHom +section + +variable [Field E] [Field E'] [Algebra F E] [Algebra F E'] + (f : E →ₐ[F] E') +include f + +variable {F} in +theorem IsSeparable.of_algHom {x : E} (h : IsSeparable F (f x)) : IsSeparable F x := by + let _ : Algebra E E' := RingHom.toAlgebra f.toRingHom haveI : IsScalarTower F E E' := IsScalarTower.of_algebraMap_eq fun x => (f.commutes x).symm - exact Algebra.isSeparable_tower_bot_of_isSeparable F E E' + exact h.tower_bot + + +variable (E') in +theorem Algebra.IsSeparable.of_algHom [Algebra.IsSeparable F E'] : Algebra.IsSeparable F E := + ⟨fun x => (Algebra.IsSeparable.isSeparable F (f x)).of_algHom⟩ + +end -lemma Algebra.IsSeparable.of_equiv_equiv {A₁ B₁ A₂ B₂ : Type*} [Field A₁] [Field B₁] +end Field + +section AlgEquiv + +variable {A₁ B₁ A₂ B₂ : Type*} [Field A₁] [Field B₁] [Field A₂] [Field B₂] [Algebra A₁ B₁] [Algebra A₂ B₂] (e₁ : A₁ ≃+* A₂) (e₂ : B₁ ≃+* B₂) (he : RingHom.comp (algebraMap A₂ B₂) ↑e₁ = RingHom.comp ↑e₂ (algebraMap A₁ B₁)) - [Algebra.IsSeparable A₁ B₁] : Algebra.IsSeparable A₂ B₂ := by +include e₁ e₂ he + +lemma IsSeparable.of_equiv_equiv {x : B₁} (h : IsSeparable A₁ x) : IsSeparable A₂ (e₂ x) := letI := e₁.toRingHom.toAlgebra letI := ((algebraMap A₁ B₁).comp e₁.symm.toRingHom).toAlgebra haveI : IsScalarTower A₁ A₂ B₁ := IsScalarTower.of_algebraMap_eq @@ -628,10 +693,15 @@ lemma Algebra.IsSeparable.of_equiv_equiv {A₁ B₁ A₂ B₂ : Type*} [Field A { e₂ with commutes' := fun r ↦ by simpa [RingHom.algebraMap_toAlgebra] using DFunLike.congr_fun he.symm (e₁.symm r) } - haveI := Algebra.isSeparable_tower_top_of_isSeparable A₁ A₂ B₁ - exact Algebra.IsSeparable.of_algHom _ _ e.symm.toAlgHom + have := IsSeparable.tower_top A₂ h + IsSeparable.of_algHom e.symm ((e₂.symm_apply_apply x).symm ▸ this) + +lemma Algebra.IsSeparable.of_equiv_equiv + [Algebra.IsSeparable A₁ B₁] : Algebra.IsSeparable A₂ B₂ := + ⟨fun x ↦ (e₂.apply_symm_apply x) ▸ _root_.IsSeparable.of_equiv_equiv e₁ e₂ he + (Algebra.IsSeparable.isSeparable _ _)⟩ -end IsSeparableTower +end AlgEquiv section CardAlgHom diff --git a/Mathlib/FieldTheory/SeparableClosure.lean b/Mathlib/FieldTheory/SeparableClosure.lean index 35439789c6f2a..596db72fdf6cd 100644 --- a/Mathlib/FieldTheory/SeparableClosure.lean +++ b/Mathlib/FieldTheory/SeparableClosure.lean @@ -115,7 +115,7 @@ theorem separableClosure.map_eq_of_separableClosure_eq_bot [Algebra E K] [IsScal (separableClosure F E).map (IsScalarTower.toAlgHom F E K) = separableClosure F K := by refine le_antisymm (map_le_of_algHom _) (fun x hx ↦ ?_) obtain ⟨y, rfl⟩ := mem_bot.1 <| h ▸ mem_separableClosure_iff.2 - (IsSeparable.of_isScalarTower E <| mem_separableClosure_iff.1 hx) + (IsSeparable.tower_top E <| mem_separableClosure_iff.1 hx) exact ⟨y, (map_mem_separableClosure_iff <| IsScalarTower.toAlgHom F E K).mp hx, rfl⟩ /-- If `i` is an `F`-algebra isomorphism of `E` and `K`, then the image of `separableClosure F E` @@ -170,7 +170,8 @@ theorem separableClosure.separableClosure_eq_bot : theorem separableClosure.normalClosure_eq_self : normalClosure F (separableClosure F E) E = separableClosure F E := le_antisymm (normalClosure_le_iff.2 fun i ↦ - haveI : Algebra.IsSeparable F i.fieldRange := (AlgEquiv.ofInjectiveField i).isSeparable + have : Algebra.IsSeparable F i.fieldRange := + (AlgEquiv.Algebra.isSeparable (AlgEquiv.ofInjectiveField i)) le_separableClosure F E _) (le_normalClosure _) /-- If `E` is normal over `F`, then the separable closure of `F` in `E` is Galois (i.e. @@ -219,7 +220,7 @@ theorem separableClosure.eq_top_iff : separableClosure F E = ⊤ ↔ Algebra.IsS `separableClosure E K`. -/ theorem separableClosure.le_restrictScalars [Algebra E K] [IsScalarTower F E K] : separableClosure F K ≤ (separableClosure E K).restrictScalars F := - fun _ h ↦ IsSeparable.of_isScalarTower E h + fun _ ↦ IsSeparable.tower_top E /-- If `K / E / F` is a field extension tower, such that `E / F` is separable, then `separableClosure F K` is equal to `separableClosure E K`. -/ diff --git a/Mathlib/FieldTheory/SeparableDegree.lean b/Mathlib/FieldTheory/SeparableDegree.lean index 054ca6596215d..3bac952cdb9f8 100644 --- a/Mathlib/FieldTheory/SeparableDegree.lean +++ b/Mathlib/FieldTheory/SeparableDegree.lean @@ -731,7 +731,7 @@ theorem finSepDegree_eq_finrank_of_isSeparable [Algebra.IsSeparable F E] : simp only at h ⊢ have heq : _ * _ = _ * _ := congr_arg₂ (· * ·) h <| (finSepDegree_adjoin_simple_eq_finrank_iff L E x (IsAlgebraic.of_finite L x)).2 <| - IsSeparable.of_isScalarTower L (Algebra.IsSeparable.isSeparable F x) + IsSeparable.tower_top L (Algebra.IsSeparable.isSeparable F x) set M := L⟮x⟯ have := Algebra.IsAlgebraic.of_finite L M rwa [finSepDegree_mul_finSepDegree_of_isAlgebraic F L M, @@ -813,7 +813,7 @@ theorem IntermediateField.isSeparable_adjoin_pair_of_isSeparable {x y : E} (hx : IsSeparable F x) (hy : IsSeparable F y) : Algebra.IsSeparable F F⟮x, y⟯ := by rw [← adjoin_simple_adjoin_simple] - replace hy := IsSeparable.of_isScalarTower F⟮x⟯ hy + replace hy := IsSeparable.tower_top F⟮x⟯ hy rw [← isSeparable_adjoin_simple_iff_isSeparable] at hx hy exact Algebra.IsSeparable.trans F F⟮x⟯ F⟮x⟯⟮y⟯ @@ -842,6 +842,19 @@ theorem isSeparable_add {x y : E} (hx : IsSeparable F x) (hy : IsSeparable F y) isSeparable_of_mem_isSeparable F E <| F⟮x, y⟯.add_mem (subset_adjoin F _ (.inl rfl)) (subset_adjoin F _ (.inr rfl)) +/-- If `x` is a separable elements, then `-x` is also a separable element. -/ +theorem isSeparable_neg {x : E} (hx : IsSeparable F x) : + IsSeparable F (-x) := + haveI := (isSeparable_adjoin_simple_iff_isSeparable F E).2 hx + isSeparable_of_mem_isSeparable F E <| F⟮x⟯.neg_mem <| mem_adjoin_simple_self F x + +/-- If `x` and `y` are both separable elements, then `x - y` is also a separable element. -/ +theorem isSeparable_sub {x y : E} (hx : IsSeparable F x) (hy : IsSeparable F y) : + IsSeparable F (x - y) := + haveI := isSeparable_adjoin_pair_of_isSeparable F E hx hy + isSeparable_of_mem_isSeparable F E <| F⟮x, y⟯.sub_mem (subset_adjoin F _ (.inl rfl)) + (subset_adjoin F _ (.inr rfl)) + /-- If `x` is a separable element, then `x⁻¹` is also a separable element. -/ theorem isSeparable_inv {x : E} (hx : IsSeparable F x) : IsSeparable F x⁻¹ := haveI := (isSeparable_adjoin_simple_iff_isSeparable F E).2 hx From 74fc63fadb6c60c2d7bf1a74cf9db7a76666b3ad Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Thu, 19 Sep 2024 08:44:21 +0000 Subject: [PATCH 037/170] feat(LocallyCompact): generalize `*Embedding.locallyCompactSpace` (#16291) to `Inducing` maps --- .../Topology/Compactness/LocallyCompact.lean | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/Mathlib/Topology/Compactness/LocallyCompact.lean b/Mathlib/Topology/Compactness/LocallyCompact.lean index 1881270210e57..2f3de63565306 100644 --- a/Mathlib/Topology/Compactness/LocallyCompact.lean +++ b/Mathlib/Topology/Compactness/LocallyCompact.lean @@ -169,28 +169,37 @@ theorem exists_compact_between [LocallyCompactSpace X] {K U : Set X} (hK : IsCom let ⟨L, hKL, hL, hLU⟩ := exists_mem_nhdsSet_isCompact_mapsTo continuous_id hK hU h_KU ⟨L, hL, subset_interior_iff_mem_nhdsSet.2 hKL, hLU⟩ +/-- If `f` is a topology inducing map with a locally compact codomain and a locally closed range, +then the domain of `f` is a locally compact space. -/ +theorem Inducing.locallyCompactSpace [LocallyCompactSpace Y] {f : X → Y} (hf : Inducing f) + (h : IsLocallyClosed (range f)) : LocallyCompactSpace X := by + rcases h with ⟨U, Z, hU, hZ, hUZ⟩ + have (x : X) : (𝓝 x).HasBasis (fun s ↦ (s ∈ 𝓝 (f x) ∧ IsCompact s) ∧ s ⊆ U) + (fun s ↦ f ⁻¹' (s ∩ Z)) := by + have H : U ∈ 𝓝 (f x) := hU.mem_nhds (hUZ.subset <| mem_range_self _).1 + rw [hf.nhds_eq_comap, ← comap_nhdsWithin_range, hUZ, + nhdsWithin_inter_of_mem (nhdsWithin_le_nhds H)] + exact (nhdsWithin_hasBasis ((compact_basis_nhds (f x)).restrict_subset H) _).comap _ + refine .of_hasBasis this fun x s ⟨⟨_, hs⟩, hsU⟩ ↦ ?_ + rw [hf.isCompact_preimage_iff] + exacts [hs.inter_right hZ, hUZ ▸ by gcongr] + protected theorem ClosedEmbedding.locallyCompactSpace [LocallyCompactSpace Y] {f : X → Y} (hf : ClosedEmbedding f) : LocallyCompactSpace X := - haveI : ∀ x : X, (𝓝 x).HasBasis (fun s => s ∈ 𝓝 (f x) ∧ IsCompact s) (f ⁻¹' ·) := fun x ↦ by - rw [hf.toInducing.nhds_eq_comap] - exact (compact_basis_nhds _).comap _ - .of_hasBasis this fun x s hs => hf.isCompact_preimage hs.2 + hf.toInducing.locallyCompactSpace hf.isClosed_range.isLocallyClosed + +protected theorem OpenEmbedding.locallyCompactSpace [LocallyCompactSpace Y] {f : X → Y} + (hf : OpenEmbedding f) : LocallyCompactSpace X := + hf.toInducing.locallyCompactSpace hf.isOpen_range.isLocallyClosed + +protected theorem IsLocallyClosed.locallyCompactSpace [LocallyCompactSpace X] {s : Set X} + (hs : IsLocallyClosed s) : LocallyCompactSpace s := + embedding_subtype_val.locallyCompactSpace <| by rwa [Subtype.range_val] protected theorem IsClosed.locallyCompactSpace [LocallyCompactSpace X] {s : Set X} (hs : IsClosed s) : LocallyCompactSpace s := - (closedEmbedding_subtype_val hs).locallyCompactSpace - -protected theorem OpenEmbedding.locallyCompactSpace [LocallyCompactSpace Y] {f : X → Y} - (hf : OpenEmbedding f) : LocallyCompactSpace X := by - have : ∀ x : X, - (𝓝 x).HasBasis (fun s ↦ (s ∈ 𝓝 (f x) ∧ IsCompact s) ∧ s ⊆ range f) (f ⁻¹' ·) := fun x ↦ by - rw [hf.nhds_eq_comap] - exact ((compact_basis_nhds _).restrict_subset <| hf.isOpen_range.mem_nhds <| - mem_range_self _).comap _ - refine .of_hasBasis this fun x s hs => ?_ - rw [hf.toInducing.isCompact_iff, image_preimage_eq_of_subset hs.2] - exact hs.1.2 + hs.isLocallyClosed.locallyCompactSpace protected theorem IsOpen.locallyCompactSpace [LocallyCompactSpace X] {s : Set X} (hs : IsOpen s) : LocallyCompactSpace s := - hs.openEmbedding_subtype_val.locallyCompactSpace + hs.isLocallyClosed.locallyCompactSpace From 0689c56444ef654d08dc20ee7f86c5cfc4e97ddc Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:24:43 +0000 Subject: [PATCH 038/170] feat: IntermediateField.adjoinRootEquivAdjoin_symm_apply_gen (#16923) --- Mathlib/FieldTheory/Adjoin.lean | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index e83645c2902e6..525d7d0c62b82 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -998,6 +998,11 @@ theorem adjoinRootEquivAdjoin_apply_root (h : IsIntegral F α) : adjoinRootEquivAdjoin F h (AdjoinRoot.root (minpoly F α)) = AdjoinSimple.gen F α := AdjoinRoot.lift_root (aeval_gen_minpoly F α) +@[simp] +theorem adjoinRootEquivAdjoin_symm_apply_gen (h : IsIntegral F α) : + (adjoinRootEquivAdjoin F h).symm (AdjoinSimple.gen F α) = AdjoinRoot.root (minpoly F α) := by + rw [AlgEquiv.symm_apply_eq, adjoinRootEquivAdjoin_apply_root] + theorem adjoin_root_eq_top (p : K[X]) [Fact (Irreducible p)] : K⟮AdjoinRoot.root p⟯ = ⊤ := (eq_adjoin_of_eq_algebra_adjoin K _ ⊤ (AdjoinRoot.adjoinRoot_eq_top (f := p)).symm).symm From d31ca8563e6e8db1130c64236aaae695ae9282c1 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:24:45 +0000 Subject: [PATCH 039/170] feat: some lemmas about polynomial roots (#16933) Co-authored-by: negiizhao --- Mathlib/Algebra/Polynomial/Roots.lean | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Mathlib/Algebra/Polynomial/Roots.lean b/Mathlib/Algebra/Polynomial/Roots.lean index 93797531db5dd..31ec3bba778f1 100644 --- a/Mathlib/Algebra/Polynomial/Roots.lean +++ b/Mathlib/Algebra/Polynomial/Roots.lean @@ -108,10 +108,13 @@ theorem ne_zero_of_mem_roots (h : a ∈ p.roots) : p ≠ 0 := theorem isRoot_of_mem_roots (h : a ∈ p.roots) : IsRoot p a := (mem_roots'.1 h).2 --- Porting note: added during port. +theorem mem_roots_map_of_injective [Semiring S] {p : S[X]} {f : S →+* R} + (hf : Function.Injective f) {x : R} (hp : p ≠ 0) : x ∈ (p.map f).roots ↔ p.eval₂ f x = 0 := by + rw [mem_roots ((Polynomial.map_ne_zero_iff hf).mpr hp), IsRoot, eval_map] + lemma mem_roots_iff_aeval_eq_zero {x : R} (w : p ≠ 0) : x ∈ roots p ↔ aeval x p = 0 := by - rw [mem_roots w, IsRoot.def, aeval_def, eval₂_eq_eval_map] - simp + rw [aeval_def, ← mem_roots_map_of_injective (NoZeroSMulDivisors.algebraMap_injective _ _) w, + Algebra.id.map_eq_id, map_id] theorem card_le_degree_of_subset_roots {p : R[X]} {Z : Finset R} (h : Z.val ⊆ p.roots) : Z.card ≤ p.natDegree := @@ -434,6 +437,13 @@ theorem aroots_monomial [CommRing S] [IsDomain S] [Algebra T S] (monomial n a).aroots S = n • ({0} : Multiset S) := by rw [← C_mul_X_pow_eq_monomial, aroots_C_mul_X_pow ha] +variable (R S) in +@[simp] +theorem aroots_map (p : T[X]) [CommRing S] [Algebra T S] [Algebra S R] [Algebra T R] + [IsScalarTower T S R] : + (p.map (algebraMap T S)).aroots R = p.aroots R := by + rw [aroots_def, aroots_def, map_map, IsScalarTower.algebraMap_eq T S R] + /-- The set of distinct roots of `p` in `S`. If you have a non-separable polynomial, use `Polynomial.aroots` for the multiset @@ -525,6 +535,12 @@ theorem rootSet_mapsTo {p : T[X]} {S S'} [CommRing S] [IsDomain S] [Algebra T S] map_injective _ (NoZeroSMulDivisors.algebraMap_injective T S') (by rwa [Polynomial.map_zero]) exact Polynomial.map_zero _ +theorem mem_rootSet_of_injective [CommRing S] {p : S[X]} [Algebra S R] + (h : Function.Injective (algebraMap S R)) {x : R} (hp : p ≠ 0) : + x ∈ p.rootSet R ↔ aeval x p = 0 := by + classical + exact Multiset.mem_toFinset.trans (mem_roots_map_of_injective h hp) + end Roots lemma eq_zero_of_natDegree_lt_card_of_eval_eq_zero {R} [CommRing R] [IsDomain R] From 094c514c02044ce08421952aef5a9fc1e8600f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 19 Sep 2024 09:56:31 +0000 Subject: [PATCH 040/170] doc(BigOperators): Explain the order of rewriting between `Finset.prod_product` and `Finset.prod_product'` (#16760) --- .../Algebra/BigOperators/Group/Finset.lean | 20 +++++++++++++------ Mathlib/Data/Fintype/BigOperators.lean | 11 +++++++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index 3b7ad688a7754..d4e712285b4a5 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -539,15 +539,18 @@ theorem prod_biUnion [DecidableEq α] {s : Finset γ} {t : γ → Finset α} (hs : Set.PairwiseDisjoint (↑s) t) : ∏ x ∈ s.biUnion t, f x = ∏ x ∈ s, ∏ i ∈ t x, f i := by rw [← disjiUnion_eq_biUnion _ _ hs, prod_disjiUnion] -/-- Product over a sigma type equals the product of fiberwise products. For rewriting +/-- The product over a sigma type equals the product of the fiberwise products. For rewriting in the reverse direction, use `Finset.prod_sigma'`. -/ -@[to_additive "Sum over a sigma type equals the sum of fiberwise sums. For rewriting +@[to_additive "The sum over a sigma type equals the sum of the fiberwise sums. For rewriting in the reverse direction, use `Finset.sum_sigma'`"] theorem prod_sigma {σ : α → Type*} (s : Finset α) (t : ∀ a, Finset (σ a)) (f : Sigma σ → β) : ∏ x ∈ s.sigma t, f x = ∏ a ∈ s, ∏ s ∈ t a, f ⟨a, s⟩ := by simp_rw [← disjiUnion_map_sigma_mk, prod_disjiUnion, prod_map, Function.Embedding.sigmaMk_apply] -@[to_additive] +/-- The product over a sigma type equals the product of the fiberwise products. For rewriting +in the reverse direction, use `Finset.prod_sigma`. -/ +@[to_additive "The sum over a sigma type equals the sum of the fiberwise sums. For rewriting +in the reverse direction, use `Finset.sum_sigma`"] theorem prod_sigma' {σ : α → Type*} (s : Finset α) (t : ∀ a, Finset (σ a)) (f : ∀ a, σ a → β) : (∏ a ∈ s, ∏ s ∈ t a, f a s) = ∏ x ∈ s.sigma t, f x.1 x.2 := Eq.symm <| prod_sigma s t fun x => f x.1 x.2 @@ -775,13 +778,18 @@ lemma prod_mul_prod_comm (f g h i : α → β) : (∏ a ∈ s, f a * g a) * ∏ a ∈ s, h a * i a = (∏ a ∈ s, f a * h a) * ∏ a ∈ s, g a * i a := by simp_rw [prod_mul_distrib, mul_mul_mul_comm] -@[to_additive] +/-- The product over a product set equals the product of the fiberwise products. For rewriting +in the reverse direction, use `Finset.prod_product'`. -/ +@[to_additive "The sum over a product set equals the sum of the fiberwise sums. For rewriting +in the reverse direction, use `Finset.sum_product'`"] theorem prod_product (s : Finset γ) (t : Finset α) (f : γ × α → β) : ∏ x ∈ s ×ˢ t, f x = ∏ x ∈ s, ∏ y ∈ t, f (x, y) := prod_finset_product (s ×ˢ t) s (fun _a => t) fun _p => mem_product -/-- An uncurried version of `Finset.prod_product`. -/ -@[to_additive "An uncurried version of `Finset.sum_product`"] +/-- The product over a product set equals the product of the fiberwise products. For rewriting +in the reverse direction, use `Finset.prod_product`. -/ +@[to_additive "The sum over a product set equals the sum of the fiberwise sums. For rewriting +in the reverse direction, use `Finset.sum_product`"] theorem prod_product' (s : Finset γ) (t : Finset α) (f : γ → α → β) : ∏ x ∈ s ×ˢ t, f x.1 x.2 = ∏ x ∈ s, ∏ y ∈ t, f x y := prod_product .. diff --git a/Mathlib/Data/Fintype/BigOperators.lean b/Mathlib/Data/Fintype/BigOperators.lean index db7502f9bc7fa..b772a62fd0956 100644 --- a/Mathlib/Data/Fintype/BigOperators.lean +++ b/Mathlib/Data/Fintype/BigOperators.lean @@ -224,13 +224,18 @@ theorem Fintype.prod_sum_type (f : α₁ ⊕ α₂ → M) : ∏ x, f x = (∏ a₁, f (Sum.inl a₁)) * ∏ a₂, f (Sum.inr a₂) := prod_disj_sum _ _ _ -@[to_additive Fintype.sum_prod_type] +/-- The product over a product type equals the product of the fiberwise products. For rewriting +in the reverse direction, use `Fintype.prod_prod_type'`. -/ +@[to_additive Fintype.sum_prod_type "The sum over a product type equals the sum of fiberwise sums. +For rewriting in the reverse direction, use `Fintype.sum_prod_type'`."] theorem Fintype.prod_prod_type [CommMonoid γ] (f : α₁ × α₂ → γ) : ∏ x, f x = ∏ x, ∏ y, f (x, y) := Finset.prod_product .. -/-- An uncurried version of `Finset.prod_prod_type`. -/ -@[to_additive Fintype.sum_prod_type' "An uncurried version of `Finset.sum_prod_type`"] +/-- The product over a product type equals the product of the fiberwise products. For rewriting +in the reverse direction, use `Fintype.prod_prod_type`. -/ +@[to_additive Fintype.sum_prod_type' "The sum over a product type equals the sum of fiberwise sums. +For rewriting in the reverse direction, use `Fintype.sum_prod_type`."] theorem Fintype.prod_prod_type' [CommMonoid γ] (f : α₁ → α₂ → γ) : ∏ x : α₁ × α₂, f x.1 x.2 = ∏ x, ∏ y, f x y := Finset.prod_product' .. From 53bac4a8080ec2954f4fabe622c903cf752df5f7 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 19 Sep 2024 10:59:00 +0000 Subject: [PATCH 041/170] chore(AlgebraicGeometry): weaken assumptions on local ring hom properties (#16897) Currently for a property of ring homomorphisms `P`, the predicate `RingHom.PropertyIsLocal P` requires `P` to be stable under composition. This predicate is meant to capture the requirements to guarantee that `affineLocally P` is local on the source and on the target. But for the latter it is sufficient to ask that `P` is stable under composition with localization maps away from one element. Hence we replace `StableUnderComposition P` and `HoldsForLocalizationAway P` with `StableUnderCompositionWithLocalizationAway P`. Before this change, every `P` satisfying `RingHom.PropertyIsLocal` was satisfied by all identities and localization maps away from one element. In particular `affineLocally P` was satisfied by all open immersions. Now this is no longer automatic, since `P` does not necessarily contain identities. This change is necessary to apply the `HasRingHomProperty` API to the class of ring homomorphisms that are standard smooth of a fixed relative dimension `n > 0`, since these are not stable under composition (the compositions add up), but are stable under composition with localization maps. This change turns some `instance`s into `theorem`s and hence slightly reduces automation. The fallout is relatively small. --- .../Morphisms/FinitePresentation.lean | 4 ++ .../Morphisms/FiniteType.lean | 4 ++ .../Morphisms/RingHomProperties.lean | 23 ++++--- Mathlib/RingTheory/LocalProperties.lean | 64 +++++++++++++++---- .../RingHom/FinitePresentation.lean | 5 +- Mathlib/RingTheory/RingHom/FiniteType.lean | 5 +- 6 files changed, 80 insertions(+), 25 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean b/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean index 384a722407c6d..d6dee82946a83 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean @@ -49,6 +49,10 @@ instance : HasRingHomProperty @LocallyOfFinitePresentation RingHom.FinitePresent instance (priority := 900) locallyOfFinitePresentation_of_isOpenImmersion [IsOpenImmersion f] : LocallyOfFinitePresentation f := HasRingHomProperty.of_isOpenImmersion + RingHom.finitePresentation_holdsForLocalizationAway.containsIdentities + +instance : MorphismProperty.IsStableUnderComposition @LocallyOfFinitePresentation := + HasRingHomProperty.stableUnderComposition RingHom.finitePresentation_stableUnderComposition instance locallyOfFinitePresentation_comp {X Y Z : Scheme.{u}} (f : X ⟶ Y) (g : Y ⟶ Z) [hf : LocallyOfFinitePresentation f] [hg : LocallyOfFinitePresentation g] : diff --git a/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean b/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean index ffc351acd412a..4424a0eed0994 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean @@ -46,6 +46,10 @@ instance : HasRingHomProperty @LocallyOfFiniteType RingHom.FiniteType where instance (priority := 900) locallyOfFiniteType_of_isOpenImmersion [IsOpenImmersion f] : LocallyOfFiniteType f := HasRingHomProperty.of_isOpenImmersion + RingHom.finiteType_holdsForLocalizationAway.containsIdentities + +instance : MorphismProperty.IsStableUnderComposition @LocallyOfFiniteType := + HasRingHomProperty.stableUnderComposition RingHom.finiteType_stableUnderComposition instance locallyOfFiniteType_comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [hf : LocallyOfFiniteType f] [hg : LocallyOfFiniteType g] : LocallyOfFiniteType (f ≫ g) := diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 3ed0b2cf6b132..fe7b94f0420b3 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -228,9 +228,8 @@ theorem of_source_openCover [IsAffine Y] | basicOpen U r H => simp_rw [Scheme.affineBasicOpen_coe, ← f.appLE_map (U := ⊤) le_top (homOfLE (X.basicOpen_le r)).op] - apply (isLocal_ringHomProperty P).StableUnderComposition _ _ H have := U.2.isLocalization_basicOpen r - apply (isLocal_ringHomProperty P).HoldsForLocalizationAway _ r + exact (isLocal_ringHomProperty P).StableUnderCompositionWithLocalizationAway.left _ r _ H | openCover U s hs H => apply (isLocal_ringHomProperty P).OfLocalizationSpanTarget.ofIsLocalization (isLocal_ringHomProperty P).respectsIso _ _ hs @@ -283,16 +282,16 @@ instance : IsLocalAtSource P := by fun i ↦ iff_of_source_openCover (P := P) (f := 𝒰.map i ≫ f) (𝒰.obj i).affineCover] simp [Scheme.OpenCover.affineRefinement, Sigma.forall] -instance : P.ContainsIdentities where +lemma containsIdentities (hP : RingHom.ContainsIdentities Q) : P.ContainsIdentities where id_mem X := by rw [IsLocalAtTarget.iff_of_iSup_eq_top (P := P) _ (iSup_affineOpens_eq_top _)] intro U have : IsAffine (𝟙 X ⁻¹ᵁ U.1) := U.2 rw [morphismRestrict_id, iff_of_isAffine (P := P), Scheme.id_app] - exact (isLocal_ringHomProperty P).HoldsForLocalizationAway.of_bijective _ _ - Function.bijective_id + apply hP -instance : P.IsStableUnderComposition where +lemma stableUnderComposition (hP : RingHom.StableUnderComposition Q) : + P.IsStableUnderComposition where comp_mem {X Y Z} f g hf hg := by wlog hZ : IsAffine Z generalizing X Y Z · rw [IsLocalAtTarget.iff_of_iSup_eq_top (P := P) _ (iSup_affineOpens_eq_top _)] @@ -311,7 +310,7 @@ instance : P.IsStableUnderComposition where rw [← Category.assoc] exact this _ (comp_of_isOpenImmersion _ _ _ hf) inferInstance rw [iff_of_isAffine (P := P)] at hf hg ⊢ - exact (isLocal_ringHomProperty P).StableUnderComposition _ _ hg hf + exact hP _ _ hg hf theorem of_comp (H : ∀ {R S T : Type u} [CommRing R] [CommRing S] [CommRing T], @@ -339,10 +338,16 @@ theorem of_comp rw [iff_of_isAffine (P := P)] at h ⊢ exact H _ _ h -instance : P.IsMultiplicative where +lemma isMultiplicative (hPc : RingHom.StableUnderComposition Q) + (hPi : RingHom.ContainsIdentities Q) : + P.IsMultiplicative where + comp_mem := (stableUnderComposition hPc).comp_mem + id_mem := (containsIdentities hPi).id_mem include Q in -lemma of_isOpenImmersion [IsOpenImmersion f] : P f := IsLocalAtSource.of_isOpenImmersion f +lemma of_isOpenImmersion (hP : RingHom.ContainsIdentities Q) [IsOpenImmersion f] : P f := + haveI : P.ContainsIdentities := containsIdentities hP + IsLocalAtSource.of_isOpenImmersion f lemma stableUnderBaseChange (hP : RingHom.StableUnderBaseChange Q) : P.StableUnderBaseChange := by apply HasAffineProperty.stableUnderBaseChange diff --git a/Mathlib/RingTheory/LocalProperties.lean b/Mathlib/RingTheory/LocalProperties.lean index 5099945fa3955..8add67ec8ef96 100644 --- a/Mathlib/RingTheory/LocalProperties.lean +++ b/Mathlib/RingTheory/LocalProperties.lean @@ -64,6 +64,10 @@ section RingHom variable (P : ∀ {R S : Type u} [CommRing R] [CommRing S] (_ : R →+* S), Prop) +/-- A property `P` of ring homs is said to contain identities if `P` holds +for the identity homomorphism of every ring. -/ +def RingHom.ContainsIdentities := ∀ (R : Type u) [CommRing R], P (RingHom.id R) + /-- A property `P` of ring homs is said to be preserved by localization if `P` holds for `M⁻¹R →+* M⁻¹S` whenever `P` holds for `R →+* S`. -/ def RingHom.LocalizationPreserves := @@ -98,6 +102,15 @@ def RingHom.HoldsForLocalizationAway : Prop := ∀ ⦃R : Type u⦄ (S : Type u) [CommRing R] [CommRing S] [Algebra R S] (r : R) [IsLocalization.Away r S], P (algebraMap R S) +/-- A property `P` of ring homs satisfies `RingHom.StableUnderCompositionWithLocalizationAway` +if whenever `P` holds for `f` it also holds for the composition with +localization maps on the left and on the right. -/ +def RingHom.StableUnderCompositionWithLocalizationAway : Prop := + (∀ ⦃R S : Type u⦄ (T : Type u) [CommRing R] [CommRing S] [CommRing T] [Algebra S T] (s : S) + [IsLocalization.Away s T] (f : R →+* S), P f → P ((algebraMap S T).comp f)) ∧ + ∀ ⦃R : Type u⦄ (S : Type u) ⦃T : Type u⦄ [CommRing R] [CommRing S] [CommRing T] [Algebra R S] + (r : R) [IsLocalization.Away r S] (f : S →+* T), P f → P (f.comp (algebraMap R S)) + /-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpanTarget` if `P` holds for `R →+* S` whenever there exists a finite set `{ r }` that spans `S` such that `P` holds for `R →+* Sᵣ`. @@ -130,8 +143,7 @@ each `{ r }` that spans `S`, we have `P (R →+* S) ↔ ∀ r, P (R →+* Sᵣ)` structure RingHom.PropertyIsLocal : Prop where LocalizationPreserves : RingHom.LocalizationPreserves @P OfLocalizationSpanTarget : RingHom.OfLocalizationSpanTarget @P - StableUnderComposition : RingHom.StableUnderComposition @P - HoldsForLocalizationAway : RingHom.HoldsForLocalizationAway @P + StableUnderCompositionWithLocalizationAway : RingHom.StableUnderCompositionWithLocalizationAway @P theorem RingHom.ofLocalizationSpan_iff_finite : RingHom.OfLocalizationSpan @P ↔ RingHom.OfLocalizationFiniteSpan @P := by @@ -168,15 +180,33 @@ theorem RingHom.HoldsForLocalizationAway.of_bijective variable {P f R' S'} +lemma RingHom.StableUnderComposition.stableUnderCompositionWithLocalizationAway + (hPc : RingHom.StableUnderComposition P) (hPl : HoldsForLocalizationAway P) : + StableUnderCompositionWithLocalizationAway P := by + constructor + · introv _ hf + exact hPc _ _ hf (hPl T s) + · introv _ hf + exact hPc _ _ (hPl S r) hf + +lemma RingHom.HoldsForLocalizationAway.containsIdentities (hPl : HoldsForLocalizationAway P) : + ContainsIdentities P := by + introv R + exact hPl.of_bijective _ _ Function.bijective_id + theorem RingHom.PropertyIsLocal.respectsIso (hP : RingHom.PropertyIsLocal @P) : RingHom.RespectsIso @P := by - apply hP.StableUnderComposition.respectsIso - introv - letI := e.toRingHom.toAlgebra - -- Porting note: was `apply_with hP.holds_for_localization_away { instances := ff }` - have : IsLocalization.Away (1 : R) S := by - apply IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective - exact RingHom.PropertyIsLocal.HoldsForLocalizationAway hP S (1 : R) + constructor + · intro R S T _ _ _ f e hf + letI := e.toRingHom.toAlgebra + have : IsLocalization.Away (1 : S) T := + IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective + exact hP.StableUnderCompositionWithLocalizationAway.left T (1 : S) f hf + · intro R S T _ _ _ f e hf + letI := e.toRingHom.toAlgebra + have : IsLocalization.Away (1 : R) S := + IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective + exact hP.StableUnderCompositionWithLocalizationAway.right S (1 : R) f hf -- Almost all arguments are implicit since this is not intended to use mid-proof. theorem RingHom.LocalizationPreserves.away (H : RingHom.LocalizationPreserves @P) (r : R) @@ -185,6 +215,15 @@ theorem RingHom.LocalizationPreserves.away (H : RingHom.LocalizationPreserves @P have : IsLocalization ((Submonoid.powers r).map f) S' := by rw [Submonoid.map_powers]; assumption exact H f (Submonoid.powers r) R' S' hf +lemma RingHom.PropertyIsLocal.HoldsForLocalizationAway (hP : RingHom.PropertyIsLocal @P) + (hPi : ContainsIdentities P) : + RingHom.HoldsForLocalizationAway @P := by + introv R _ + have : algebraMap R S = (algebraMap R S).comp (RingHom.id R) := by simp + rw [this] + apply (hP.StableUnderCompositionWithLocalizationAway).left S r + apply hPi + theorem RingHom.PropertyIsLocal.ofLocalizationSpan (hP : RingHom.PropertyIsLocal @P) : RingHom.OfLocalizationSpan @P := by introv R hs hs' @@ -192,9 +231,10 @@ theorem RingHom.PropertyIsLocal.ofLocalizationSpan (hP : RingHom.PropertyIsLocal rw [Ideal.map_span, Ideal.map_top] at hs apply hP.OfLocalizationSpanTarget _ _ hs rintro ⟨_, r, hr, rfl⟩ - convert hP.StableUnderComposition - _ _ (hP.HoldsForLocalizationAway (Localization.Away r) r) (hs' ⟨r, hr⟩) using 1 - exact (IsLocalization.map_comp _).symm + rw [← IsLocalization.map_comp (M := Submonoid.powers r) (S := Localization.Away r) + (T := Submonoid.powers (f r))] + apply hP.StableUnderCompositionWithLocalizationAway.right _ r + exact hs' ⟨r, hr⟩ lemma RingHom.OfLocalizationSpanTarget.ofIsLocalization (hP : RingHom.OfLocalizationSpanTarget P) (hP' : RingHom.RespectsIso P) diff --git a/Mathlib/RingTheory/RingHom/FinitePresentation.lean b/Mathlib/RingTheory/RingHom/FinitePresentation.lean index 99b90e6894081..ad4ae18aa6419 100644 --- a/Mathlib/RingTheory/RingHom/FinitePresentation.lean +++ b/Mathlib/RingTheory/RingHom/FinitePresentation.lean @@ -163,8 +163,9 @@ theorem finitePresentation_ofLocalizationSpanTarget : /-- Being finitely-presented is a local property of rings. -/ theorem finitePresentation_isLocal : PropertyIsLocal @FinitePresentation := ⟨finitePresentation_localizationPreserves, - finitePresentation_ofLocalizationSpanTarget, finitePresentation_stableUnderComposition, - finitePresentation_holdsForLocalizationAway⟩ + finitePresentation_ofLocalizationSpanTarget, + finitePresentation_stableUnderComposition.stableUnderCompositionWithLocalizationAway + finitePresentation_holdsForLocalizationAway⟩ /-- Being finitely-presented respects isomorphisms. -/ theorem finitePresentation_respectsIso : RingHom.RespectsIso @RingHom.FinitePresentation := diff --git a/Mathlib/RingTheory/RingHom/FiniteType.lean b/Mathlib/RingTheory/RingHom/FiniteType.lean index fb75176c50b6e..3f927873decf1 100644 --- a/Mathlib/RingTheory/RingHom/FiniteType.lean +++ b/Mathlib/RingTheory/RingHom/FiniteType.lean @@ -88,8 +88,9 @@ theorem finiteType_ofLocalizationSpanTarget : OfLocalizationSpanTarget @FiniteTy · rw [ht]; trivial theorem finiteType_is_local : PropertyIsLocal @FiniteType := - ⟨localization_finiteType, finiteType_ofLocalizationSpanTarget, finiteType_stableUnderComposition, - finiteType_holdsForLocalizationAway⟩ + ⟨localization_finiteType, finiteType_ofLocalizationSpanTarget, + finiteType_stableUnderComposition.stableUnderCompositionWithLocalizationAway + finiteType_holdsForLocalizationAway⟩ theorem finiteType_respectsIso : RingHom.RespectsIso @RingHom.FiniteType := RingHom.finiteType_is_local.respectsIso From fa4fb4cb990487e2687d4a0faeb1f72c8ed4a19e Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:11:32 +0000 Subject: [PATCH 042/170] chore: update Mathlib dependencies 2024-09-19 (#16941) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index 61c218e567c74..e358556ad3d13 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "565ce2c97c20428195f8e7861cc0fb1f537e4d25", + "rev": "dee1ae2c06d16e68e9b3e52ba80771c9da40f986", "name": "LeanSearchClient", "manifestFile": "lake-manifest.json", "inputRev": "main", From b3592187c3974b66371b622ca78ea672de312162 Mon Sep 17 00:00:00 2001 From: Dagur Asgeirsson Date: Thu, 19 Sep 2024 11:58:38 +0000 Subject: [PATCH 043/170] feat(Topology): the partition of a space into fibers of a function (#15527) --- Mathlib.lean | 2 + Mathlib/Logic/Function/FiberPartition.lean | 71 ++++++++++++++++++++++ Mathlib/Topology/FiberPartition.lean | 69 +++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 Mathlib/Logic/Function/FiberPartition.lean create mode 100644 Mathlib/Topology/FiberPartition.lean diff --git a/Mathlib.lean b/Mathlib.lean index 925312093dff7..adf13fdfa4748 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3137,6 +3137,7 @@ import Mathlib.Logic.Function.Basic import Mathlib.Logic.Function.CompTypeclasses import Mathlib.Logic.Function.Conjugate import Mathlib.Logic.Function.Defs +import Mathlib.Logic.Function.FiberPartition import Mathlib.Logic.Function.FromTypes import Mathlib.Logic.Function.Iterate import Mathlib.Logic.Function.OfArity @@ -4586,6 +4587,7 @@ import Mathlib.Topology.FiberBundle.Basic import Mathlib.Topology.FiberBundle.Constructions import Mathlib.Topology.FiberBundle.IsHomeomorphicTrivialBundle import Mathlib.Topology.FiberBundle.Trivialization +import Mathlib.Topology.FiberPartition import Mathlib.Topology.Filter import Mathlib.Topology.GDelta import Mathlib.Topology.Germ diff --git a/Mathlib/Logic/Function/FiberPartition.lean b/Mathlib/Logic/Function/FiberPartition.lean new file mode 100644 index 0000000000000..c9d2f8a334e71 --- /dev/null +++ b/Mathlib/Logic/Function/FiberPartition.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2024 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.Data.Set.Basic +/-! + +This file defines the type `f.Fiber` of fibers of a function `f : Y → Z`, and provides some API +to work with and construct terms of this type. + +Note: this API is designed to be useful when defining the counit of the adjunction between +the functor which takes a set to the condensed set corresponding to locally constant maps to that +set, and the forgetful functor from the category of condensed sets to the category of sets +(see PR #14027). +-/ + +variable {X Y Z : Type*} + +namespace Function + +/-- The indexing set of the partition. -/ +def Fiber (f : Y → Z) : Type _ := Set.range (fun (x : Set.range f) ↦ f ⁻¹' {x.val}) + +namespace Fiber + +/-- +Any `a : Fiber f` is of the form `f ⁻¹' {x}` for some `x` in the image of `f`. We define `a.image`  +as an arbitrary such `x`. +-/ +noncomputable def image (f : Y → Z) (a : Fiber f) : Z := a.2.choose.1 + +lemma eq_fiber_image (f : Y → Z) (a : Fiber f) : a.1 = f ⁻¹' {a.image} := a.2.choose_spec.symm + +/-- +Given `y : Y`, `Fiber.mk f y` is the fiber of `f` that `y` belongs to, as an element of `Fiber f`. +-/ +def mk (f : Y → Z) (y : Y) : Fiber f := ⟨f ⁻¹' {f y}, by simp⟩ + +/-- `y : Y` as a term of the type `Fiber.mk f y` -/ +def mkSelf (f : Y → Z) (y : Y) : (mk f y).val := ⟨y, rfl⟩ + +lemma map_eq_image (f : Y → Z) (a : Fiber f) (x : a.1) : f x = a.image := by + have := a.2.choose_spec + rw [← Set.mem_singleton_iff, ← Set.mem_preimage] + convert x.prop + +lemma mk_image (f : Y → Z) (y : Y) : (Fiber.mk f y).image = f y := + (map_eq_image (x := mkSelf f y)).symm + +lemma mem_iff_eq_image (f : Y → Z) (y : Y) (a : Fiber f) : y ∈ a.val ↔ f y = a.image := + ⟨fun h ↦ a.map_eq_image _ ⟨y, h⟩, fun h ↦ by rw [a.eq_fiber_image]; exact h⟩ + +/-- An arbitrary element of `a : Fiber f`. -/ +noncomputable def preimage (f : Y → Z) (a : Fiber f) : Y := a.2.choose.2.choose + +lemma map_preimage_eq_image (f : Y → Z) (a : Fiber f) : f a.preimage = a.image := + a.2.choose.2.choose_spec + +lemma fiber_nonempty (f : Y → Z) (a : Fiber f) : Set.Nonempty a.val := by + refine ⟨preimage f a, ?_⟩ + rw [mem_iff_eq_image, ← map_preimage_eq_image] + +lemma map_preimage_eq_image_map {W : Type*} (f : Y → Z) (g : Z → W) (a : Fiber (g ∘ f)) : + g (f a.preimage) = a.image := by rw [← map_preimage_eq_image]; rfl + +lemma image_eq_image_mk (f : Y → Z) (g : X → Y) (a : Fiber (f ∘ g)) : + a.image = (Fiber.mk f (g (a.preimage _))).image := by + rw [← map_preimage_eq_image_map _ _ a, mk_image] + +end Function.Fiber diff --git a/Mathlib/Topology/FiberPartition.lean b/Mathlib/Topology/FiberPartition.lean new file mode 100644 index 0000000000000..c01b90f3fe77b --- /dev/null +++ b/Mathlib/Topology/FiberPartition.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2024 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.Topology.LocallyConstant.Basic +import Mathlib.Logic.Function.FiberPartition +/-! + +This file provides some API surrounding `Function.Fiber` (see +`Mathlib.Logic.Function.FiberPartition`) in the presence of a topology on the domain of the +function. + +Note: this API is designed to be useful when defining the counit of the adjunction between +the functor which takes a set to the condensed set corresponding to locally constant maps to that +set, and the forgetful functor from the category of condensed sets to the category of sets +(see PR #14027). +-/ + + +open Function + +variable {S Y : Type*} (f : S → Y) + +namespace TopologicalSpace.Fiber + +variable [TopologicalSpace S] + +/-- The canonical map from the disjoint union induced by `f` to `S`. -/ +@[simps apply] +def sigmaIsoHom : C((x : Fiber f) × x.val, S) where + toFun := fun ⟨a, x⟩ ↦ x.val + +lemma sigmaIsoHom_inj : Function.Injective (sigmaIsoHom f) := by + rintro ⟨⟨_, _, rfl⟩, ⟨_, hx⟩⟩ ⟨⟨_, _, rfl⟩, ⟨_, hy⟩⟩ h + refine Sigma.subtype_ext ?_ h + simp only [sigmaIsoHom_apply] at h + rw [Set.mem_preimage, Set.mem_singleton_iff] at hx hy + simp [← hx, ← hy, h] + +lemma sigmaIsoHom_surj : Function.Surjective (sigmaIsoHom f) := + fun _ ↦ ⟨⟨⟨_, ⟨⟨_, Set.mem_range_self _⟩, rfl⟩⟩, ⟨_, rfl⟩⟩, rfl⟩ + +/-- The inclusion map from a component of the disjoint union induced by `f` into `S`. -/ +def sigmaIncl (a : Fiber f) : C(a.val, S) where + toFun := fun x ↦ x.val + +/-- The inclusion map from a fiber of a composition into the intermediate fiber. -/ +def sigmaInclIncl {X : Type*} (g : Y → X) (a : Fiber (g ∘ f)) + (b : Fiber (f ∘ (sigmaIncl (g ∘ f) a))) : + C(b.val, (Fiber.mk f (b.preimage).val).val) where + toFun x := ⟨x.val.val, by + have := x.prop + simp only [sigmaIncl, ContinuousMap.coe_mk, Fiber.mem_iff_eq_image, comp_apply] at this + rw [Fiber.mem_iff_eq_image, Fiber.mk_image, this, ← Fiber.map_preimage_eq_image] + rfl⟩ + +variable (l : LocallyConstant S Y) [CompactSpace S] + +instance (x : Fiber l) : CompactSpace x.val := by + obtain ⟨y, hy⟩ := x.prop + rw [← isCompact_iff_compactSpace, ← hy] + exact (l.2.isClosed_fiber _).isCompact + +instance : Finite (Fiber l) := + have : Finite (Set.range l) := l.range_finite + Finite.Set.finite_range _ + +end TopologicalSpace.Fiber From 3f70ca89bab28b8341318b28021c7b790a64b1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 19 Sep 2024 11:58:39 +0000 Subject: [PATCH 044/170] chore: generalise the binary rearrangement inequality (#16940) --- Mathlib/Algebra/Order/Module/Defs.lean | 75 ++++++++++++++------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/Mathlib/Algebra/Order/Module/Defs.lean b/Mathlib/Algebra/Order/Module/Defs.lean index fbf1c3d4a4b3b..0b51dcd81ec13 100644 --- a/Mathlib/Algebra/Order/Module/Defs.lean +++ b/Mathlib/Algebra/Order/Module/Defs.lean @@ -6,6 +6,7 @@ Authors: Yaël Dillies import Mathlib.Algebra.Module.Defs import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.GroupWithZero.Action.Synonym +import Mathlib.Tactic.GCongr import Mathlib.Tactic.Positivity.Core /-! @@ -769,7 +770,7 @@ instance instPosSMulReflectLE [PosSMulReflectLE α β] : PosSMulReflectLE α β end Left section Right -variable [Preorder α] [Ring α] [OrderedAddCommGroup β] [Module α β] +variable [Preorder α] [Monoid α] [OrderedAddCommGroup β] [DistribMulAction α β] instance instSMulPosMono [SMulPosMono α β] : SMulPosMono α βᵒᵈ where elim _b hb a₁ a₂ ha := by @@ -794,6 +795,45 @@ instance instSMulPosReflectLE [SMulPosReflectLE α β] : SMulPosReflectLE α β end Right end OrderDual +section OrderedAddCommMonoid +variable [StrictOrderedSemiring α] [ExistsAddOfLE α] [OrderedCancelAddCommMonoid β] + [Module α β] + +section PosSMulMono +variable [PosSMulMono α β] {a₁ a₂ : α} {b₁ b₂ : β} + +/-- Binary **rearrangement inequality**. -/ +lemma smul_add_smul_le_smul_add_smul (ha : a₁ ≤ a₂) (hb : b₁ ≤ b₂) : + a₁ • b₂ + a₂ • b₁ ≤ a₁ • b₁ + a₂ • b₂ := by + obtain ⟨a, ha₀, rfl⟩ := exists_nonneg_add_of_le ha + rw [add_smul, add_smul, add_left_comm] + gcongr + +/-- Binary **rearrangement inequality**. -/ +lemma smul_add_smul_le_smul_add_smul' (ha : a₂ ≤ a₁) (hb : b₂ ≤ b₁) : + a₁ • b₂ + a₂ • b₁ ≤ a₁ • b₁ + a₂ • b₂ := by + simp_rw [add_comm (a₁ • _)]; exact smul_add_smul_le_smul_add_smul ha hb + +end PosSMulMono + +section PosSMulStrictMono +variable [PosSMulStrictMono α β] {a₁ a₂ : α} {b₁ b₂ : β} + +/-- Binary strict **rearrangement inequality**. -/ +lemma smul_add_smul_lt_smul_add_smul (ha : a₁ < a₂) (hb : b₁ < b₂) : + a₁ • b₂ + a₂ • b₁ < a₁ • b₁ + a₂ • b₂ := by + obtain ⟨a, ha₀, rfl⟩ := lt_iff_exists_pos_add.1 ha + rw [add_smul, add_smul, add_left_comm] + gcongr + +/-- Binary strict **rearrangement inequality**. -/ +lemma smul_add_smul_lt_smul_add_smul' (ha : a₂ < a₁) (hb : b₂ < b₁) : + a₁ • b₂ + a₂ • b₁ < a₁ • b₁ + a₂ • b₂ := by + simp_rw [add_comm (a₁ • _)]; exact smul_add_smul_lt_smul_add_smul ha hb + +end PosSMulStrictMono +end OrderedAddCommMonoid + section OrderedRing variable [OrderedRing α] @@ -864,39 +904,6 @@ lemma smul_neg_iff_of_neg_left (ha : a < 0) : a • b < 0 ↔ 0 < b := by simpa only [smul_zero] using smul_lt_smul_iff_of_neg_left ha (b₂ := (0 : β)) end PosSMulStrictMono - -/-- Binary **rearrangement inequality**. -/ -lemma smul_add_smul_le_smul_add_smul [PosSMulMono α β] - {b₁ b₂ : α} {a d : β} (hab : b₁ ≤ b₂) (hcd : a ≤ d) : b₁ • d + b₂ • a ≤ b₁ • a + b₂ • d := by - obtain ⟨b₂, rfl⟩ := exists_add_of_le hab - obtain ⟨d, rfl⟩ := exists_add_of_le hcd - rw [smul_add, add_right_comm, smul_add, ← add_assoc, add_smul _ _ d] - rw [le_add_iff_nonneg_right] at hab hcd - exact add_le_add_left (le_add_of_nonneg_right <| smul_nonneg hab hcd) _ - -/-- Binary **rearrangement inequality**. -/ -lemma smul_add_smul_le_smul_add_smul' [PosSMulMono α β] - {b₁ b₂ : α} {a d : β} (hba : b₂ ≤ b₁) (hdc : d ≤ a) : b₁ • d + b₂ • a ≤ b₁ • a + b₂ • d := by - rw [add_comm (b₁ • d), add_comm (b₁ • a)] - exact smul_add_smul_le_smul_add_smul hba hdc - -/-- Binary strict **rearrangement inequality**. -/ -lemma smul_add_smul_lt_smul_add_smul [PosSMulStrictMono α β] - {b₁ b₂ : α} {a d : β} (hab : b₁ < b₂) (hcd : a < d) : - b₁ • d + b₂ • a < b₁ • a + b₂ • d := by - obtain ⟨b₂, rfl⟩ := exists_add_of_le hab.le - obtain ⟨d, rfl⟩ := exists_add_of_le hcd.le - rw [smul_add, add_right_comm, smul_add, ← add_assoc, add_smul _ _ d] - rw [lt_add_iff_pos_right] at hab hcd - exact add_lt_add_left (lt_add_of_pos_right _ <| smul_pos hab hcd) _ - -/-- Binary strict **rearrangement inequality**. -/ -lemma smul_add_smul_lt_smul_add_smul' [PosSMulStrictMono α β] - {b₁ b₂ : α} {a d : β} (hba : b₂ < b₁) (hdc : d < a) : - b₁ • d + b₂ • a < b₁ • a + b₂ • d := by - rw [add_comm (b₁ • d), add_comm (b₁ • a)] - exact smul_add_smul_lt_smul_add_smul hba hdc - end OrderedAddCommGroup section LinearOrderedAddCommGroup From 0e7d55443d22f4e179f761356d0247fd2e122c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 19 Sep 2024 12:35:29 +0000 Subject: [PATCH 045/170] chore: rename `Holder` to `Hoelder` (#16870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As indicated by https://en.wikipedia.org/wiki/Germanic_umlaut#Substitution, Hölder should be transcribed to Hoelder in ASCII. --- Mathlib/MeasureTheory/Measure/Hausdorff.lean | 9 +- Mathlib/Order/JordanHolder.lean | 44 ++--- Mathlib/RingTheory/SimpleModule.lean | 2 +- .../MetricSpace/HausdorffDimension.lean | 28 ++-- Mathlib/Topology/MetricSpace/Holder.lean | 153 +++++++++--------- docs/overview.yaml | 2 +- docs/undergrad.yaml | 2 +- scripts/nolints.json | 4 +- 8 files changed, 123 insertions(+), 121 deletions(-) diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 84bfe07b9e3fb..7f66fdd905d67 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -667,13 +667,13 @@ open MeasureTheory MeasureTheory.Measure variable [MeasurableSpace X] [BorelSpace X] [MeasurableSpace Y] [BorelSpace Y] -namespace HolderOnWith +namespace HoelderOnWith variable {C r : ℝ≥0} {f : X → Y} {s t : Set X} /-- If `f : X → Y` is Hölder continuous on `s` with a positive exponent `r`, then `μH[d] (f '' s) ≤ C ^ d * μH[r * d] s`. -/ -theorem hausdorffMeasure_image_le (h : HolderOnWith C r f s) (hr : 0 < r) {d : ℝ} (hd : 0 ≤ d) : +theorem hausdorffMeasure_image_le (h : HoelderOnWith C r f s) (hr : 0 < r) {d : ℝ} (hd : 0 ≤ d) : μH[d] (f '' s) ≤ (C : ℝ≥0∞) ^ d * μH[r * d] s := by -- We start with the trivial case `C = 0` rcases (zero_le C).eq_or_lt with (rfl | hC0) @@ -711,7 +711,7 @@ theorem hausdorffMeasure_image_le (h : HolderOnWith C r f s) (hr : 0 < r) {d : rw [ENNReal.rpow_mul, ← ENNReal.mul_rpow_of_nonneg _ _ hd] exact ENNReal.rpow_le_rpow (h.ediam_image_inter_le _) hd -end HolderOnWith +end HoelderOnWith namespace LipschitzOnWith @@ -720,7 +720,8 @@ variable {K : ℝ≥0} {f : X → Y} {s t : Set X} /-- If `f : X → Y` is `K`-Lipschitz on `s`, then `μH[d] (f '' s) ≤ K ^ d * μH[d] s`. -/ theorem hausdorffMeasure_image_le (h : LipschitzOnWith K f s) {d : ℝ} (hd : 0 ≤ d) : μH[d] (f '' s) ≤ (K : ℝ≥0∞) ^ d * μH[d] s := by - simpa only [NNReal.coe_one, one_mul] using h.holderOnWith.hausdorffMeasure_image_le zero_lt_one hd + simpa only [NNReal.coe_one, one_mul] + using h.HoelderOnWith.hausdorffMeasure_image_le zero_lt_one hd end LipschitzOnWith diff --git a/Mathlib/Order/JordanHolder.lean b/Mathlib/Order/JordanHolder.lean index 5657d2eff114d..26ce206f68732 100644 --- a/Mathlib/Order/JordanHolder.lean +++ b/Mathlib/Order/JordanHolder.lean @@ -13,16 +13,16 @@ import Mathlib.Order.RelSeries /-! # Jordan-Hölder Theorem -This file proves the Jordan Hölder theorem for a `JordanHolderLattice`, a class also defined in -this file. Examples of `JordanHolderLattice` include `Subgroup G` if `G` is a group, and +This file proves the Jordan Hölder theorem for a `JordanHoelderLattice`, a class also defined in +this file. Examples of `JordanHoelderLattice` include `Subgroup G` if `G` is a group, and `Submodule R M` if `M` is an `R`-module. Using this approach the theorem need not be proved separately for both groups and modules, the proof in this file can be applied to both. ## Main definitions -The main definitions in this file are `JordanHolderLattice` and `CompositionSeries`, +The main definitions in this file are `JordanHoelderLattice` and `CompositionSeries`, and the relation `Equivalent` on `CompositionSeries` -A `JordanHolderLattice` is the class for which the Jordan Hölder theorem is proved. A +A `JordanHoelderLattice` is the class for which the Jordan Hölder theorem is proved. A Jordan Hölder lattice is a lattice equipped with a notion of maximality, `IsMaximal`, and a notion of isomorphism of pairs `Iso`. In the example of subgroups of a group, `IsMaximal H K` means that `H` is a maximal normal subgroup of `K`, and `Iso (H₁, K₁) (H₂, K₂)` means that the quotient @@ -42,30 +42,30 @@ Two `CompositionSeries X`, `s₁` and `s₂` are equivalent if there is a biject ## Main theorems -The main theorem is `CompositionSeries.jordan_holder`, which says that if two composition +The main theorem is `CompositionSeries.jordan_hoelder`, which says that if two composition series have the same least element and the same largest element, then they are `Equivalent`. ## TODO -Provide instances of `JordanHolderLattice` for subgroups, and potentially for modular lattices. +Provide instances of `JordanHoelderLattice` for subgroups, and potentially for modular lattices. It is not entirely clear how this should be done. Possibly there should be no global instances -of `JordanHolderLattice`, and the instances should only be defined locally in order to prove +of `JordanHoelderLattice`, and the instances should only be defined locally in order to prove the Jordan-Hölder theorem for modules/groups and the API should be transferred because many of the theorems in this file will have stronger versions for modules. There will also need to be an API for mapping composition series across homomorphisms. It is also probably possible to -provide an instance of `JordanHolderLattice` for any `ModularLattice`, and in this case the +provide an instance of `JordanHoelderLattice` for any `ModularLattice`, and in this case the Jordan-Hölder theorem will say that there is a well defined notion of length of a modular lattice. -However an instance of `JordanHolderLattice` for a modular lattice will not be able to contain +However an instance of `JordanHoelderLattice` for a modular lattice will not be able to contain the correct notion of isomorphism for modules, so a separate instance for modules will still be required and this will clash with the instance for modular lattices, and so at least one of these instances should not be a global instance. > [!NOTE] -> The previous paragraph indicates that the instance of `JordanHolderLattice` for submodules should +> The previous paragraph indicates that the instance of `JordanHoelderLattice` for submodules should > be obtained via `ModularLattice`. This is not the case in `mathlib4`. -> See `JordanHolderModule.instJordanHolderLattice`. +> See `JordanHolderModule.instJordanHoelderLattice`. -/ @@ -73,7 +73,7 @@ universe u open Set RelSeries -/-- A `JordanHolderLattice` is the class for which the Jordan Hölder theorem is proved. A +/-- A `JordanHoelderLattice` is the class for which the Jordan Hölder theorem is proved. A Jordan Hölder lattice is a lattice equipped with a notion of maximality, `IsMaximal`, and a notion of isomorphism of pairs `Iso`. In the example of subgroups of a group, `IsMaximal H K` means that `H` is a maximal normal subgroup of `K`, and `Iso (H₁, K₁) (H₂, K₂)` means that the quotient @@ -81,7 +81,7 @@ of isomorphism of pairs `Iso`. In the example of subgroups of a group, `IsMaxima satisfy the second isomorphism theorem `Iso (H, H ⊔ K) (H ⊓ K, K)`. Examples include `Subgroup G` if `G` is a group, and `Submodule R M` if `M` is an `R`-module. -/ -class JordanHolderLattice (X : Type u) [Lattice X] where +class JordanHoelderLattice (X : Type u) [Lattice X] where IsMaximal : X → X → Prop lt_of_isMaximal : ∀ {x y}, IsMaximal x y → x < y sup_eq_of_isMaximal : ∀ {x y z}, IsMaximal x z → IsMaximal y z → x ≠ y → x ⊔ y = z @@ -92,9 +92,9 @@ class JordanHolderLattice (X : Type u) [Lattice X] where iso_trans : ∀ {x y z}, Iso x y → Iso y z → Iso x z second_iso : ∀ {x y}, IsMaximal x (x ⊔ y) → Iso (x, x ⊔ y) (x ⊓ y, y) -namespace JordanHolderLattice +namespace JordanHoelderLattice -variable {X : Type u} [Lattice X] [JordanHolderLattice X] +variable {X : Type u} [Lattice X] [JordanHoelderLattice X] theorem isMaximal_inf_right_of_isMaximal_sup {x y : X} (hxz : IsMaximal x (x ⊔ y)) (hyz : IsMaximal y (x ⊔ y)) : IsMaximal (x ⊓ y) y := by @@ -115,27 +115,27 @@ theorem IsMaximal.iso_refl {x y : X} (h : IsMaximal x y) : Iso (x, y) (x, y) := second_iso_of_eq h (sup_eq_right.2 (le_of_lt (lt_of_isMaximal h))) (inf_eq_left.2 (le_of_lt (lt_of_isMaximal h))) -end JordanHolderLattice +end JordanHoelderLattice -open JordanHolderLattice +open JordanHoelderLattice attribute [symm] iso_symm attribute [trans] iso_trans /-- A `CompositionSeries X` is a finite nonempty series of elements of a -`JordanHolderLattice` such that each element is maximal inside the next. The length of a +`JordanHoelderLattice` such that each element is maximal inside the next. The length of a `CompositionSeries X` is one less than the number of elements in the series. Note that there is no stipulation that a series start from the bottom of the lattice and finish at the top. For a composition series `s`, `s.last` is the largest element of the series, and `s.head` is the least element. -/ -abbrev CompositionSeries (X : Type u) [Lattice X] [JordanHolderLattice X] : Type u := +abbrev CompositionSeries (X : Type u) [Lattice X] [JordanHoelderLattice X] : Type u := RelSeries (IsMaximal (X := X)) namespace CompositionSeries -variable {X : Type u} [Lattice X] [JordanHolderLattice X] +variable {X : Type u} [Lattice X] [JordanHoelderLattice X] theorem lt_succ (s : CompositionSeries X) (i : Fin s.length) : s (Fin.castSucc i) < s (Fin.succ i) := @@ -407,9 +407,9 @@ theorem exists_last_eq_snoc_equivalent (s : CompositionSeries X) (x : X) (hm : I (second_iso_of_eq (isMaximal_eraseLast_last h0s) (sup_eq_of_isMaximal (isMaximal_eraseLast_last h0s) hm hetx) (by rw [inf_comm, htt])) -/-- The **Jordan-Hölder** theorem, stated for any `JordanHolderLattice`. +/-- The **Jordan-Hölder** theorem, stated for any `JordanHoelderLattice`. If two composition series start and finish at the same place, they are equivalent. -/ -theorem jordan_holder (s₁ s₂ : CompositionSeries X) +theorem jordan_hoelder (s₁ s₂ : CompositionSeries X) (hb : s₁.head = s₂.head) (ht : s₁.last = s₂.last) : Equivalent s₁ s₂ := by induction' hle : s₁.length with n ih generalizing s₁ s₂ diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 5bc001188d6d1..8195ae6a8c17f 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -428,7 +428,7 @@ theorem second_iso {X Y : Submodule R M} (_ : X ⋖ X ⊔ Y) : dsimp exact (LinearMap.quotientInfEquivSupQuotient Y X).symm -instance instJordanHolderLattice : JordanHolderLattice (Submodule R M) where +instance instJordanHoelderLattice : JordanHoelderLattice (Submodule R M) where IsMaximal := (· ⋖ ·) lt_of_isMaximal := CovBy.lt sup_eq_of_isMaximal hxz hyz := WCovBy.sup_eq hxz.wcovBy hyz.wcovBy diff --git a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean index 1018155f553a7..d2b889b56f214 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean @@ -40,9 +40,9 @@ properties of Hausdorff dimension. ### (Pre)images under (anti)lipschitz and Hölder continuous maps -* `HolderWith.dimH_image_le` etc: if `f : X → Y` is Hölder continuous with exponent `r > 0`, then - for any `s`, `dimH (f '' s) ≤ dimH s / r`. We prove versions of this statement for `HolderWith`, - `HolderOnWith`, and locally Hölder maps, as well as for `Set.image` and `Set.range`. +* `HoelderWith.dimH_image_le` etc: if `f : X → Y` is Hölder continuous with exponent `r > 0`, then + for any `s`, `dimH (f '' s) ≤ dimH s / r`. We prove versions of this statement for `HoelderWith`, + `HoelderOnWith`, and locally Hölder maps, as well as for `Set.image` and `Set.range`. * `LipschitzWith.dimH_image_le` etc: Lipschitz continuous maps do not increase the Hausdorff dimension of sets. * for a map that is known to be both Lipschitz and antilipschitz (e.g., for an `Isometry` or @@ -257,7 +257,7 @@ end variable {C K r : ℝ≥0} {f : X → Y} {s t : Set X} /-- If `f` is a Hölder continuous map with exponent `r > 0`, then `dimH (f '' s) ≤ dimH s / r`. -/ -theorem HolderOnWith.dimH_image_le (h : HolderOnWith C r f s) (hr : 0 < r) : +theorem HoelderOnWith.dimH_image_le (h : HoelderOnWith C r f s) (hr : 0 < r) : dimH (f '' s) ≤ dimH s / r := by borelize X Y refine dimH_le fun d hd => ?_ @@ -270,28 +270,28 @@ theorem HolderOnWith.dimH_image_le (h : HolderOnWith C r f s) (hr : 0 < r) : exacts [le_dimH_of_hausdorffMeasure_eq_top Hrd, Or.inl (mt ENNReal.coe_eq_zero.1 hr.ne'), Or.inl ENNReal.coe_ne_top] -namespace HolderWith +namespace HoelderWith /-- If `f : X → Y` is Hölder continuous with a positive exponent `r`, then the Hausdorff dimension of the image of a set `s` is at most `dimH s / r`. -/ -theorem dimH_image_le (h : HolderWith C r f) (hr : 0 < r) (s : Set X) : +theorem dimH_image_le (h : HoelderWith C r f) (hr : 0 < r) (s : Set X) : dimH (f '' s) ≤ dimH s / r := - (h.holderOnWith s).dimH_image_le hr + (h.HoelderOnWith s).dimH_image_le hr /-- If `f` is a Hölder continuous map with exponent `r > 0`, then the Hausdorff dimension of its range is at most the Hausdorff dimension of its domain divided by `r`. -/ -theorem dimH_range_le (h : HolderWith C r f) (hr : 0 < r) : +theorem dimH_range_le (h : HoelderWith C r f) (hr : 0 < r) : dimH (range f) ≤ dimH (univ : Set X) / r := @image_univ _ _ f ▸ h.dimH_image_le hr univ -end HolderWith +end HoelderWith /-- If `s` is a set in a space `X` with second countable topology and `f : X → Y` is Hölder continuous in a neighborhood within `s` of every point `x ∈ s` with the same positive exponent `r` but possibly different coefficients, then the Hausdorff dimension of the image `f '' s` is at most the Hausdorff dimension of `s` divided by `r`. -/ theorem dimH_image_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ≥0} {f : X → Y} - (hr : 0 < r) {s : Set X} (hf : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HolderOnWith C r f t) : + (hr : 0 < r) {s : Set X} (hf : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HoelderOnWith C r f t) : dimH (f '' s) ≤ dimH s / r := by choose! C t htn hC using hf rcases countable_cover_nhdsWithin htn with ⟨u, hus, huc, huU⟩ @@ -303,7 +303,7 @@ theorem dimH_image_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ positive exponent `r` but possibly different coefficients, then the Hausdorff dimension of the range of `f` is at most the Hausdorff dimension of `X` divided by `r`. -/ theorem dimH_range_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ≥0} {f : X → Y} - (hr : 0 < r) (hf : ∀ x : X, ∃ C : ℝ≥0, ∃ s ∈ 𝓝 x, HolderOnWith C r f s) : + (hr : 0 < r) (hf : ∀ x : X, ∃ C : ℝ≥0, ∃ s ∈ 𝓝 x, HoelderOnWith C r f s) : dimH (range f) ≤ dimH (univ : Set X) / r := by rw [← image_univ] refine dimH_image_le_of_locally_holder_on hr fun x _ => ?_ @@ -316,7 +316,7 @@ theorem dimH_range_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ /-- If `f : X → Y` is Lipschitz continuous on `s`, then `dimH (f '' s) ≤ dimH s`. -/ theorem LipschitzOnWith.dimH_image_le (h : LipschitzOnWith K f s) : dimH (f '' s) ≤ dimH s := by - simpa using h.holderOnWith.dimH_image_le zero_lt_one + simpa using h.HoelderOnWith.dimH_image_le zero_lt_one namespace LipschitzWith @@ -336,8 +336,8 @@ is Lipschitz in a neighborhood within `s` of every point `x ∈ s`, then the Hau the image `f '' s` is at most the Hausdorff dimension of `s`. -/ theorem dimH_image_le_of_locally_lipschitzOn [SecondCountableTopology X] {f : X → Y} {s : Set X} (hf : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, LipschitzOnWith C f t) : dimH (f '' s) ≤ dimH s := by - have : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HolderOnWith C 1 f t := by - simpa only [holderOnWith_one] using hf + have : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HoelderOnWith C 1 f t := by + simpa only [hoelderOnWith_one] using hf simpa only [ENNReal.coe_one, div_one] using dimH_image_le_of_locally_holder_on zero_lt_one this /-- If `f : X → Y` is Lipschitz in a neighborhood of each point `x : X`, then the Hausdorff diff --git a/Mathlib/Topology/MetricSpace/Holder.lean b/Mathlib/Topology/MetricSpace/Holder.lean index da0e2b14c4f81..0aeb043310269 100644 --- a/Mathlib/Topology/MetricSpace/Holder.lean +++ b/Mathlib/Topology/MetricSpace/Holder.lean @@ -14,9 +14,9 @@ properties of Hölder continuous functions. ## Main definitions -* `HolderOnWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and +* `HoelderOnWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and exponent `r : ℝ≥0` on a set `s`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y ∈ s`; -* `HolderWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and exponent +* `HoelderWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and exponent `r : ℝ≥0`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y : X`. ## Implementation notes @@ -41,81 +41,82 @@ open NNReal ENNReal Topology section Emetric -variable [PseudoEMetricSpace X] [PseudoEMetricSpace Y] [PseudoEMetricSpace Z] +variable [PseudoEMetricSpace X] [PseudoEMetricSpace Y] [PseudoEMetricSpace Z] {C r : ℝ≥0} + {f : X → Y} /-- A function `f : X → Y` between two `PseudoEMetricSpace`s is Hölder continuous with constant `C : ℝ≥0` and exponent `r : ℝ≥0`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y : X`. -/ -def HolderWith (C r : ℝ≥0) (f : X → Y) : Prop := +def HoelderWith (C r : ℝ≥0) (f : X → Y) : Prop := ∀ x y, edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) /-- A function `f : X → Y` between two `PseudoEMetricSpace`s is Hölder continuous with constant `C : ℝ≥0` and exponent `r : ℝ≥0` on a set `s : Set X`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y ∈ s`. -/ -def HolderOnWith (C r : ℝ≥0) (f : X → Y) (s : Set X) : Prop := +def HoelderOnWith (C r : ℝ≥0) (f : X → Y) (s : Set X) : Prop := ∀ x ∈ s, ∀ y ∈ s, edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) @[simp] -theorem holderOnWith_empty (C r : ℝ≥0) (f : X → Y) : HolderOnWith C r f ∅ := fun _ hx => hx.elim +theorem hoelderOnWith_empty (C r : ℝ≥0) (f : X → Y) : HoelderOnWith C r f ∅ := fun _ hx => hx.elim @[simp] -theorem holderOnWith_singleton (C r : ℝ≥0) (f : X → Y) (x : X) : HolderOnWith C r f {x} := by +theorem hoelderOnWith_singleton (C r : ℝ≥0) (f : X → Y) (x : X) : HoelderOnWith C r f {x} := by rintro a (rfl : a = x) b (rfl : b = a) rw [edist_self] exact zero_le _ -theorem Set.Subsingleton.holderOnWith {s : Set X} (hs : s.Subsingleton) (C r : ℝ≥0) (f : X → Y) : - HolderOnWith C r f s := - hs.induction_on (holderOnWith_empty C r f) (holderOnWith_singleton C r f) +theorem Set.Subsingleton.HoelderOnWith {s : Set X} (hs : s.Subsingleton) (C r : ℝ≥0) (f : X → Y) : + HoelderOnWith C r f s := + hs.induction_on (hoelderOnWith_empty C r f) (hoelderOnWith_singleton C r f) -theorem holderOnWith_univ {C r : ℝ≥0} {f : X → Y} : HolderOnWith C r f univ ↔ HolderWith C r f := by - simp only [HolderOnWith, HolderWith, mem_univ, true_imp_iff] +lemma hoelderOnWith_univ : HoelderOnWith C r f univ ↔ HoelderWith C r f := by + simp only [HoelderOnWith, HoelderWith, mem_univ, true_imp_iff] @[simp] -theorem holderOnWith_one {C : ℝ≥0} {f : X → Y} {s : Set X} : - HolderOnWith C 1 f s ↔ LipschitzOnWith C f s := by - simp only [HolderOnWith, LipschitzOnWith, NNReal.coe_one, ENNReal.rpow_one] +theorem hoelderOnWith_one {C : ℝ≥0} {f : X → Y} {s : Set X} : + HoelderOnWith C 1 f s ↔ LipschitzOnWith C f s := by + simp only [HoelderOnWith, LipschitzOnWith, NNReal.coe_one, ENNReal.rpow_one] -alias ⟨_, LipschitzOnWith.holderOnWith⟩ := holderOnWith_one +alias ⟨_, LipschitzOnWith.HoelderOnWith⟩ := hoelderOnWith_one @[simp] -theorem holderWith_one {C : ℝ≥0} {f : X → Y} : HolderWith C 1 f ↔ LipschitzWith C f := - holderOnWith_univ.symm.trans <| holderOnWith_one.trans lipschitzOnWith_univ +theorem hoelderWith_one {C : ℝ≥0} {f : X → Y} : HoelderWith C 1 f ↔ LipschitzWith C f := + hoelderOnWith_univ.symm.trans <| hoelderOnWith_one.trans lipschitzOnWith_univ -alias ⟨_, LipschitzWith.holderWith⟩ := holderWith_one +alias ⟨_, LipschitzWith.HoelderWith⟩ := hoelderWith_one -theorem holderWith_id : HolderWith 1 1 (id : X → X) := - LipschitzWith.id.holderWith +theorem hoelderWith_id : HoelderWith 1 1 (id : X → X) := + LipschitzWith.id.HoelderWith -protected theorem HolderWith.holderOnWith {C r : ℝ≥0} {f : X → Y} (h : HolderWith C r f) - (s : Set X) : HolderOnWith C r f s := fun x _ y _ => h x y +protected theorem HoelderWith.HoelderOnWith {C r : ℝ≥0} {f : X → Y} (h : HoelderWith C r f) + (s : Set X) : HoelderOnWith C r f s := fun x _ y _ => h x y -namespace HolderOnWith +namespace HoelderOnWith variable {C r : ℝ≥0} {f : X → Y} {s t : Set X} -theorem edist_le (h : HolderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) : +theorem edist_le (h : HoelderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) := h x hx y hy -theorem edist_le_of_le (h : HolderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) {d : ℝ≥0∞} +theorem edist_le_of_le (h : HoelderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) {d : ℝ≥0∞} (hd : edist x y ≤ d) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := (h.edist_le hx hy).trans <| by gcongr -theorem comp {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HolderOnWith Cg rg g t) {Cf rf : ℝ≥0} - {f : X → Y} (hf : HolderOnWith Cf rf f s) (hst : MapsTo f s t) : - HolderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := by +theorem comp {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HoelderOnWith Cg rg g t) {Cf rf : ℝ≥0} + {f : X → Y} (hf : HoelderOnWith Cf rf f s) (hst : MapsTo f s t) : + HoelderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := by intro x hx y hy rw [ENNReal.coe_mul, mul_comm rg, NNReal.coe_mul, ENNReal.rpow_mul, mul_assoc, ENNReal.coe_rpow_of_nonneg _ rg.coe_nonneg, ← ENNReal.mul_rpow_of_nonneg _ _ rg.coe_nonneg] exact hg.edist_le_of_le (hst hx) (hst hy) (hf.edist_le hx hy) -theorem comp_holderWith {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HolderOnWith Cg rg g t) - {Cf rf : ℝ≥0} {f : X → Y} (hf : HolderWith Cf rf f) (ht : ∀ x, f x ∈ t) : - HolderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := - holderOnWith_univ.mp <| hg.comp (hf.holderOnWith univ) fun x _ => ht x +theorem comp_hoelderWith {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HoelderOnWith Cg rg g t) + {Cf rf : ℝ≥0} {f : X → Y} (hf : HoelderWith Cf rf f) (ht : ∀ x, f x ∈ t) : + HoelderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := + hoelderOnWith_univ.mp <| hg.comp (hf.HoelderOnWith univ) fun x _ => ht x /-- A Hölder continuous function is uniformly continuous -/ -protected theorem uniformContinuousOn (hf : HolderOnWith C r f s) (h0 : 0 < r) : +protected theorem uniformContinuousOn (hf : HoelderOnWith C r f s) (h0 : 0 < r) : UniformContinuousOn f s := by refine EMetric.uniformContinuousOn_iff.2 fun ε εpos => ?_ have : Tendsto (fun d : ℝ≥0∞ => (C : ℝ≥0∞) * d ^ (r : ℝ)) (𝓝 0) (𝓝 0) := @@ -123,86 +124,86 @@ protected theorem uniformContinuousOn (hf : HolderOnWith C r f s) (h0 : 0 < r) : rcases ENNReal.nhds_zero_basis.mem_iff.1 (this (gt_mem_nhds εpos)) with ⟨δ, δ0, H⟩ exact ⟨δ, δ0, fun hx y hy h => (hf.edist_le hx hy).trans_lt (H h)⟩ -protected theorem continuousOn (hf : HolderOnWith C r f s) (h0 : 0 < r) : ContinuousOn f s := +protected theorem continuousOn (hf : HoelderOnWith C r f s) (h0 : 0 < r) : ContinuousOn f s := (hf.uniformContinuousOn h0).continuousOn -protected theorem mono (hf : HolderOnWith C r f s) (ht : t ⊆ s) : HolderOnWith C r f t := +protected theorem mono (hf : HoelderOnWith C r f s) (ht : t ⊆ s) : HoelderOnWith C r f t := fun _ hx _ hy => hf.edist_le (ht hx) (ht hy) -theorem ediam_image_le_of_le (hf : HolderOnWith C r f s) {d : ℝ≥0∞} (hd : EMetric.diam s ≤ d) : +theorem ediam_image_le_of_le (hf : HoelderOnWith C r f s) {d : ℝ≥0∞} (hd : EMetric.diam s ≤ d) : EMetric.diam (f '' s) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := EMetric.diam_image_le_iff.2 fun _ hx _ hy => hf.edist_le_of_le hx hy <| (EMetric.edist_le_diam_of_mem hx hy).trans hd -theorem ediam_image_le (hf : HolderOnWith C r f s) : +theorem ediam_image_le (hf : HoelderOnWith C r f s) : EMetric.diam (f '' s) ≤ (C : ℝ≥0∞) * EMetric.diam s ^ (r : ℝ) := hf.ediam_image_le_of_le le_rfl -theorem ediam_image_le_of_subset (hf : HolderOnWith C r f s) (ht : t ⊆ s) : +theorem ediam_image_le_of_subset (hf : HoelderOnWith C r f s) (ht : t ⊆ s) : EMetric.diam (f '' t) ≤ (C : ℝ≥0∞) * EMetric.diam t ^ (r : ℝ) := (hf.mono ht).ediam_image_le -theorem ediam_image_le_of_subset_of_le (hf : HolderOnWith C r f s) (ht : t ⊆ s) {d : ℝ≥0∞} +theorem ediam_image_le_of_subset_of_le (hf : HoelderOnWith C r f s) (ht : t ⊆ s) {d : ℝ≥0∞} (hd : EMetric.diam t ≤ d) : EMetric.diam (f '' t) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := (hf.mono ht).ediam_image_le_of_le hd -theorem ediam_image_inter_le_of_le (hf : HolderOnWith C r f s) {d : ℝ≥0∞} +theorem ediam_image_inter_le_of_le (hf : HoelderOnWith C r f s) {d : ℝ≥0∞} (hd : EMetric.diam t ≤ d) : EMetric.diam (f '' (t ∩ s)) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := hf.ediam_image_le_of_subset_of_le inter_subset_right <| (EMetric.diam_mono inter_subset_left).trans hd -theorem ediam_image_inter_le (hf : HolderOnWith C r f s) (t : Set X) : +theorem ediam_image_inter_le (hf : HoelderOnWith C r f s) (t : Set X) : EMetric.diam (f '' (t ∩ s)) ≤ (C : ℝ≥0∞) * EMetric.diam t ^ (r : ℝ) := hf.ediam_image_inter_le_of_le le_rfl -end HolderOnWith +end HoelderOnWith -namespace HolderWith +namespace HoelderWith variable {C r : ℝ≥0} {f : X → Y} -theorem edist_le (h : HolderWith C r f) (x y : X) : +theorem edist_le (h : HoelderWith C r f) (x y : X) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) := h x y -theorem edist_le_of_le (h : HolderWith C r f) {x y : X} {d : ℝ≥0∞} (hd : edist x y ≤ d) : +theorem edist_le_of_le (h : HoelderWith C r f) {x y : X} {d : ℝ≥0∞} (hd : edist x y ≤ d) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := - (h.holderOnWith univ).edist_le_of_le trivial trivial hd + (h.HoelderOnWith univ).edist_le_of_le trivial trivial hd -theorem comp {Cg rg : ℝ≥0} {g : Y → Z} (hg : HolderWith Cg rg g) {Cf rf : ℝ≥0} {f : X → Y} - (hf : HolderWith Cf rf f) : HolderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := - (hg.holderOnWith univ).comp_holderWith hf fun _ => trivial +theorem comp {Cg rg : ℝ≥0} {g : Y → Z} (hg : HoelderWith Cg rg g) {Cf rf : ℝ≥0} {f : X → Y} + (hf : HoelderWith Cf rf f) : HoelderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := + (hg.HoelderOnWith univ).comp_hoelderWith hf fun _ => trivial -theorem comp_holderOnWith {Cg rg : ℝ≥0} {g : Y → Z} (hg : HolderWith Cg rg g) {Cf rf : ℝ≥0} - {f : X → Y} {s : Set X} (hf : HolderOnWith Cf rf f s) : - HolderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := - (hg.holderOnWith univ).comp hf fun _ _ => trivial +theorem comp_hoelderOnWith {Cg rg : ℝ≥0} {g : Y → Z} (hg : HoelderWith Cg rg g) {Cf rf : ℝ≥0} + {f : X → Y} {s : Set X} (hf : HoelderOnWith Cf rf f s) : + HoelderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := + (hg.HoelderOnWith univ).comp hf fun _ _ => trivial /-- A Hölder continuous function is uniformly continuous -/ -protected theorem uniformContinuous (hf : HolderWith C r f) (h0 : 0 < r) : UniformContinuous f := - uniformContinuousOn_univ.mp <| (hf.holderOnWith univ).uniformContinuousOn h0 +protected theorem uniformContinuous (hf : HoelderWith C r f) (h0 : 0 < r) : UniformContinuous f := + uniformContinuousOn_univ.mp <| (hf.HoelderOnWith univ).uniformContinuousOn h0 -protected theorem continuous (hf : HolderWith C r f) (h0 : 0 < r) : Continuous f := +protected theorem continuous (hf : HoelderWith C r f) (h0 : 0 < r) : Continuous f := (hf.uniformContinuous h0).continuous -theorem ediam_image_le (hf : HolderWith C r f) (s : Set X) : +theorem ediam_image_le (hf : HoelderWith C r f) (s : Set X) : EMetric.diam (f '' s) ≤ (C : ℝ≥0∞) * EMetric.diam s ^ (r : ℝ) := EMetric.diam_image_le_iff.2 fun _ hx _ hy => hf.edist_le_of_le <| EMetric.edist_le_diam_of_mem hx hy lemma const {y : Y} : - HolderWith C r (Function.const X y) := fun x₁ x₂ => by + HoelderWith C r (Function.const X y) := fun x₁ x₂ => by simp only [Function.const_apply, edist_self, zero_le] -lemma zero [Zero Y] : HolderWith C r (0 : X → Y) := .const +lemma zero [Zero Y] : HoelderWith C r (0 : X → Y) := .const -lemma of_isEmpty [IsEmpty X] : HolderWith C r f := isEmptyElim +lemma of_isEmpty [IsEmpty X] : HoelderWith C r f := isEmptyElim -lemma mono {C' : ℝ≥0} (hf : HolderWith C r f) (h : C ≤ C') : - HolderWith C' r f := +lemma mono {C' : ℝ≥0} (hf : HoelderWith C r f) (h : C ≤ C') : + HoelderWith C' r f := fun x₁ x₂ ↦ (hf x₁ x₂).trans (mul_right_mono (coe_le_coe.2 h)) -end HolderWith +end HoelderWith end Emetric @@ -210,30 +211,30 @@ section PseudoMetric variable [PseudoMetricSpace X] [PseudoMetricSpace Y] {C r : ℝ≥0} {f : X → Y} -namespace HolderWith +namespace HoelderWith -theorem nndist_le_of_le (hf : HolderWith C r f) {x y : X} {d : ℝ≥0} (hd : nndist x y ≤ d) : +theorem nndist_le_of_le (hf : HoelderWith C r f) {x y : X} {d : ℝ≥0} (hd : nndist x y ≤ d) : nndist (f x) (f y) ≤ C * d ^ (r : ℝ) := by rw [← ENNReal.coe_le_coe, ← edist_nndist, ENNReal.coe_mul, ENNReal.coe_rpow_of_nonneg _ r.coe_nonneg] apply hf.edist_le_of_le rwa [edist_nndist, ENNReal.coe_le_coe] -theorem nndist_le (hf : HolderWith C r f) (x y : X) : +theorem nndist_le (hf : HoelderWith C r f) (x y : X) : nndist (f x) (f y) ≤ C * nndist x y ^ (r : ℝ) := hf.nndist_le_of_le le_rfl -theorem dist_le_of_le (hf : HolderWith C r f) {x y : X} {d : ℝ} (hd : dist x y ≤ d) : +theorem dist_le_of_le (hf : HoelderWith C r f) {x y : X} {d : ℝ} (hd : dist x y ≤ d) : dist (f x) (f y) ≤ C * d ^ (r : ℝ) := by lift d to ℝ≥0 using dist_nonneg.trans hd rw [dist_nndist] at hd ⊢ norm_cast at hd ⊢ exact hf.nndist_le_of_le hd -theorem dist_le (hf : HolderWith C r f) (x y : X) : dist (f x) (f y) ≤ C * dist x y ^ (r : ℝ) := +theorem dist_le (hf : HoelderWith C r f) (x y : X) : dist (f x) (f y) ≤ C * dist x y ^ (r : ℝ) := hf.dist_le_of_le le_rfl -end HolderWith +end HoelderWith end PseudoMetric @@ -242,7 +243,7 @@ section Metric variable [PseudoMetricSpace X] [MetricSpace Y] {C r : ℝ≥0} {f : X → Y} @[simp] -lemma holderWith_zero_iff : HolderWith 0 r f ↔ ∀ x₁ x₂, f x₁ = f x₂ := by +lemma hoelderWith_zero_iff : HoelderWith 0 r f ↔ ∀ x₁ x₂, f x₁ = f x₂ := by refine ⟨fun h x₁ x₂ => ?_, fun h x₁ x₂ => h x₁ x₂ ▸ ?_⟩ · specialize h x₁ x₂ simp [ENNReal.coe_zero, zero_mul, nonpos_iff_eq_zero, edist_eq_zero] at h @@ -255,20 +256,20 @@ section SeminormedAddCommGroup variable [PseudoMetricSpace X] [SeminormedAddCommGroup Y] {C C' r : ℝ≥0} {f g : X → Y} -namespace HolderWith +namespace HoelderWith -lemma add (hf : HolderWith C r f) (hg : HolderWith C' r g) : - HolderWith (C + C') r (f + g) := fun x₁ x₂ => by +lemma add (hf : HoelderWith C r f) (hg : HoelderWith C' r g) : + HoelderWith (C + C') r (f + g) := fun x₁ x₂ => by refine le_trans (edist_add_add_le _ _ _ _) <| le_trans (add_le_add (hf x₁ x₂) (hg x₁ x₂)) ?_ rw [coe_add, add_mul] lemma smul {α} [NormedDivisionRing α] [Module α Y] [BoundedSMul α Y] (a : α) - (hf : HolderWith C r f) : HolderWith (C * ‖a‖₊) r (a • f) := fun x₁ x₂ => by + (hf : HoelderWith C r f) : HoelderWith (C * ‖a‖₊) r (a • f) := fun x₁ x₂ => by rw [Pi.smul_apply, coe_mul, Pi.smul_apply, edist_smul₀, mul_comm (C : ℝ≥0∞), ENNReal.smul_def, smul_eq_mul, mul_assoc] gcongr exact hf x₁ x₂ -end HolderWith +end HoelderWith end SeminormedAddCommGroup diff --git a/docs/overview.yaml b/docs/overview.yaml index be28612dbf810..1c28518967b6a 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -247,7 +247,7 @@ Topology: sequential compactness is equivalent to compactness (Bolzano-Weierstrass): 'UniformSpace.isCompact_iff_isSeqCompact' Heine-Borel theorem (proper metric space version): 'Metric.isCompact_iff_isClosed_bounded' Lipschitz continuity: 'LipschitzWith' - Hölder continuity: 'HolderWith' + Hölder continuity: 'HoelderWith' contraction mapping theorem: 'ContractingWith.exists_fixedPoint' Baire theorem: 'dense_iInter_of_isOpen' Arzela-Ascoli theorem: 'BoundedContinuousFunction.arzela_ascoli' diff --git a/docs/undergrad.yaml b/docs/undergrad.yaml index 21619980559e5..0ed700ef27967 100644 --- a/docs/undergrad.yaml +++ b/docs/undergrad.yaml @@ -517,7 +517,7 @@ Measures and integral calculus: differentiability of integrals with respect to parameters: '' $\mathrm{L}^p$ spaces where $1 ≤ p ≤ ∞$: 'MeasureTheory.Lp' Completeness of $\mathrm{L}^p$ spaces: 'MeasureTheory.Lp.instCompleteSpace' - Holder's inequality: 'NNReal.lintegral_mul_le_Lp_mul_Lq' + Hölder's inequality: 'NNReal.lintegral_mul_le_Lp_mul_Lq' Fubini's theorem: 'MeasureTheory.integral_prod' change of variables for multiple integrals: 'MeasureTheory.integral_image_eq_integral_abs_det_fderiv_smul' change of variables to polar co-ordinates: 'integral_comp_polarCoord_symm' diff --git a/scripts/nolints.json b/scripts/nolints.json index 197243db4c7e0..d4e5bb4d35641 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -193,8 +193,8 @@ ["docBlame", "Isocrystal.«term_≃ᶠⁱ[_,_]_»"], ["docBlame", "Isocrystal.«termΦ(_,_)»"], ["docBlame", "Isocrystal.«termφ(_,_)»"], - ["docBlame", "JordanHolderLattice.IsMaximal"], - ["docBlame", "JordanHolderLattice.Iso"], + ["docBlame", "JordanHoelderLattice.IsMaximal"], + ["docBlame", "JordanHoelderLattice.Iso"], ["docBlame", "Kronecker.«term_⊗ₖ_»"], ["docBlame", "Kronecker.«term_⊗ₖₜ[_]_»"], ["docBlame", "Kronecker.«term_⊗ₖₜ_»"], From 4a7a86018479e49ef3efd7e7732438e186c3d371 Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:06:16 +0000 Subject: [PATCH 046/170] chore: update Mathlib dependencies 2024-09-19 (#16945) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index e358556ad3d13..05d82c3f77869 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "dee1ae2c06d16e68e9b3e52ba80771c9da40f986", + "rev": "2ba60fa2c384a94735454db11a2d523612eaabff", "name": "LeanSearchClient", "manifestFile": "lake-manifest.json", "inputRev": "main", From 8e9838b850aee39812977a1cd4ad9f4b7c67cc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 19 Sep 2024 13:48:56 +0000 Subject: [PATCH 047/170] chore: Rename `Holder` to `Hoelder` in file names (#16947) --- Mathlib.lean | 4 ++-- Mathlib/MeasureTheory/Measure/Hausdorff.lean | 2 +- Mathlib/Order/{JordanHolder.lean => JordanHoelder.lean} | 2 +- Mathlib/RingTheory/SimpleModule.lean | 8 ++++---- .../Topology/MetricSpace/{Holder.lean => Hoelder.lean} | 0 5 files changed, 8 insertions(+), 8 deletions(-) rename Mathlib/Order/{JordanHolder.lean => JordanHoelder.lean} (99%) rename Mathlib/Topology/MetricSpace/{Holder.lean => Hoelder.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index adf13fdfa4748..6be5ea0a0fee1 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3656,7 +3656,7 @@ import Mathlib.Order.Interval.Set.WithBotTop import Mathlib.Order.Irreducible import Mathlib.Order.IsWellOrderLimitElement import Mathlib.Order.Iterate -import Mathlib.Order.JordanHolder +import Mathlib.Order.JordanHoelder import Mathlib.Order.KonigLemma import Mathlib.Order.KrullDimension import Mathlib.Order.Lattice @@ -4655,7 +4655,7 @@ import Mathlib.Topology.MetricSpace.GromovHausdorff import Mathlib.Topology.MetricSpace.GromovHausdorffRealized import Mathlib.Topology.MetricSpace.HausdorffDimension import Mathlib.Topology.MetricSpace.HausdorffDistance -import Mathlib.Topology.MetricSpace.Holder +import Mathlib.Topology.MetricSpace.Hoelder import Mathlib.Topology.MetricSpace.Infsep import Mathlib.Topology.MetricSpace.IsometricSMul import Mathlib.Topology.MetricSpace.Isometry diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 7f66fdd905d67..9c35a5a589469 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -6,7 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Analysis.Convex.Between import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic import Mathlib.MeasureTheory.Measure.Lebesgue.Basic -import Mathlib.Topology.MetricSpace.Holder +import Mathlib.Topology.MetricSpace.Hoelder import Mathlib.Topology.MetricSpace.MetricSeparated /-! diff --git a/Mathlib/Order/JordanHolder.lean b/Mathlib/Order/JordanHoelder.lean similarity index 99% rename from Mathlib/Order/JordanHolder.lean rename to Mathlib/Order/JordanHoelder.lean index 26ce206f68732..0ac4f362de12e 100644 --- a/Mathlib/Order/JordanHolder.lean +++ b/Mathlib/Order/JordanHoelder.lean @@ -65,7 +65,7 @@ instances should not be a global instance. > [!NOTE] > The previous paragraph indicates that the instance of `JordanHoelderLattice` for submodules should > be obtained via `ModularLattice`. This is not the case in `mathlib4`. -> See `JordanHolderModule.instJordanHoelderLattice`. +> See `JordanHoelderModule.instJordanHoelderLattice`. -/ diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 8195ae6a8c17f..29555b158d300 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -5,7 +5,7 @@ Authors: Aaron Anderson -/ import Mathlib.LinearAlgebra.Isomorphisms import Mathlib.LinearAlgebra.Projection -import Mathlib.Order.JordanHolder +import Mathlib.Order.JordanHoelder import Mathlib.Order.CompactlyGenerated.Intervals import Mathlib.LinearAlgebra.FiniteDimensional @@ -405,9 +405,9 @@ noncomputable instance _root_.Module.End.divisionRing end LinearMap -- Porting note: adding a namespace with all the new statements; existing result is not used in ML3 -namespace JordanHolderModule +namespace JordanHoelderModule --- Porting note: jordanHolderModule was timing out so outlining the fields +-- Porting note: jordanHoelderModule was timing out so outlining the fields /-- An isomorphism `X₂ / X₁ ∩ X₂ ≅ Y₂ / Y₁ ∩ Y₂` of modules for pairs `(X₁,X₂) (Y₁,Y₂) : Submodule R M` -/ @@ -438,4 +438,4 @@ instance instJordanHoelderLattice : JordanHoelderLattice (Submodule R M) where iso_trans := iso_trans second_iso := second_iso -end JordanHolderModule +end JordanHoelderModule diff --git a/Mathlib/Topology/MetricSpace/Holder.lean b/Mathlib/Topology/MetricSpace/Hoelder.lean similarity index 100% rename from Mathlib/Topology/MetricSpace/Holder.lean rename to Mathlib/Topology/MetricSpace/Hoelder.lean From c7d8aad65f87bd237cb3ef45c664deb75af7c565 Mon Sep 17 00:00:00 2001 From: haitian-yuki <127060846+yukiniu@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:09:28 +0000 Subject: [PATCH 048/170] feat: Multiset lemmas (#15645) Co-authored-by: Malvin Gattinger --- Mathlib/Data/Multiset/Basic.lean | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index ea61402c98cb6..9cd7fc8586622 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -2346,6 +2346,24 @@ theorem map_count_True_eq_filter_card (s : Multiset α) (p : α → Prop) [Decid simp only [count_eq_card_filter_eq, filter_map, card_map, Function.id_comp, eq_true_eq_id, Function.comp_apply] +@[simp] theorem sub_singleton [DecidableEq α] (a : α) (s : Multiset α) : s - {a} = s.erase a := by + ext + simp only [count_sub, count_singleton] + split <;> simp_all + +theorem mem_sub [DecidableEq α] {a : α} {s t : Multiset α} : + a ∈ s - t ↔ t.count a < s.count a := by + rw [← count_pos, count_sub, Nat.sub_pos_iff_lt] + +theorem inter_add_sub_of_add_eq_add [DecidableEq α] {M N P Q : Multiset α} (h : M + N = P + Q) : + (N ∩ Q) + (P - M) = N := by + ext x + rw [Multiset.count_add, Multiset.count_inter, Multiset.count_sub] + have h0 : M.count x + N.count x = P.count x + Q.count x := by + rw [Multiset.ext] at h + simp_all only [Multiset.mem_add, Multiset.count_add] + omega + /-! ### Lift a relation to `Multiset`s -/ From 1458edb5e63dff5ac6934be66ab9422d67ac42ec Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 19 Sep 2024 16:02:25 +0000 Subject: [PATCH 049/170] feat(RingTheory): composition of presentations (#16727) Given an `R`-algebra `S` and an `S`-algebra `T` with presentations `P` and `Q` we construct the canonical `R`-presentation of `T`. This contribution was created as part of the AIM workshop "Formalizing algebraic geometry" in June 2024. --- Mathlib/Algebra/MvPolynomial/Equiv.lean | 12 ++ Mathlib/RingTheory/Ideal/Maps.lean | 22 ++++ Mathlib/RingTheory/Polynomial/Basic.lean | 5 + Mathlib/RingTheory/Presentation.lean | 158 ++++++++++++++++++++++- 4 files changed, 195 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 7b6e4a464b071..6b59003105ae6 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -255,6 +255,18 @@ def sumAlgEquiv : MvPolynomial (S₁ ⊕ S₂) R ≃ₐ[R] MvPolynomial S₁ (Mv simp only [sumRingEquiv, mvPolynomialEquivMvPolynomial, Equiv.toFun_as_coe, Equiv.coe_fn_mk, B, sumToIter_C, A] } +lemma sumAlgEquiv_comp_rename_inr : + (sumAlgEquiv R S₁ S₂).toAlgHom.comp (rename Sum.inr) = IsScalarTower.toAlgHom R + (MvPolynomial S₂ R) (MvPolynomial S₁ (MvPolynomial S₂ R)) := by + ext i + simp + +lemma sumAlgEquiv_comp_rename_inl : + (sumAlgEquiv R S₁ S₂).toAlgHom.comp (rename Sum.inl) = + MvPolynomial.mapAlgHom (Algebra.ofId _ _) := by + ext i + simp + section -- this speeds up typeclass search in the lemma below diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index 8b0482cf861a6..f26dd00db1d4a 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -125,11 +125,21 @@ theorem comap_comap {T : Type*} [Semiring T] {I : Ideal T} (f : R →+* S) (g : (I.comap g).comap f = I.comap (g.comp f) := rfl +lemma comap_comapₐ {R A B C : Type*} [CommSemiring R] [Semiring A] [Algebra R A] [Semiring B] + [Algebra R B] [Semiring C] [Algebra R C] {I : Ideal C} (f : A →ₐ[R] B) (g : B →ₐ[R] C) : + (I.comap g).comap f = I.comap (g.comp f) := + I.comap_comap f.toRingHom g.toRingHom + theorem map_map {T : Type*} [Semiring T] {I : Ideal R} (f : R →+* S) (g : S →+* T) : (I.map f).map g = I.map (g.comp f) := ((gc_map_comap f).compose (gc_map_comap g)).l_unique (gc_map_comap (g.comp f)) fun _ => comap_comap _ _ +lemma map_mapₐ {R A B C : Type*} [CommSemiring R] [Semiring A] [Algebra R A] [Semiring B] + [Algebra R B] [Semiring C] [Algebra R C] {I : Ideal A} (f : A →ₐ[R] B) (g : B →ₐ[R] C) : + (I.map f).map g = I.map (g.comp f) := + I.map_map f.toRingHom g.toRingHom + theorem map_span (f : F) (s : Set R) : map f (span s) = span (f '' s) := by refine (Submodule.span_eq_of_le _ ?_ ?_).symm · rintro _ ⟨x, hx, rfl⟩; exact mem_map_of_mem f (subset_span hx) @@ -433,6 +443,10 @@ theorem comap_le_iff_le_map (hf : Function.Bijective f) {I : Ideal R} {K : Ideal ⟨fun h => le_map_of_comap_le_of_surjective f hf.right h, fun h => (relIsoOfBijective f hf).right_inv I ▸ comap_mono h⟩ +lemma comap_map_of_bijective (hf : Function.Bijective f) {I : Ideal R} : + (I.map f).comap f = I := + le_antisymm ((comap_le_iff_le_map f hf).mpr fun _ ↦ id) le_comap_map + theorem map.isMaximal (hf : Function.Bijective f) {I : Ideal R} (H : IsMaximal I) : IsMaximal (map f I) := by refine @@ -645,6 +659,10 @@ section Ring variable [Ring R] [Ring S] [FunLike F R S] [rc : RingHomClass F R S] +lemma comap_map_of_surjective' (f : F) (hf : Function.Surjective f) (I : Ideal R) : + (I.map f).comap f = I ⊔ RingHom.ker f := + comap_map_of_surjective f hf I + theorem map_sInf {A : Set (Ideal R)} {f : F} (hf : Function.Surjective f) : (∀ J ∈ A, RingHom.ker f ≤ J) → map f (sInf A) = sInf (map f '' A) := by refine fun h => le_antisymm (le_sInf ?_) ?_ @@ -807,6 +825,10 @@ lemma coe_ker : RingHom.ker f = RingHom.ker (f : A →+* B) := rfl lemma coe_ideal_map (I : Ideal A) : Ideal.map f I = Ideal.map (f : A →+* B) I := rfl +lemma comap_ker {C : Type*} [Semiring C] [Algebra R C] (f : B →ₐ[R] C) (g : A →ₐ[R] B) : + (RingHom.ker f).comap g = RingHom.ker (f.comp g) := + RingHom.comap_ker f.toRingHom g.toRingHom + end AlgHom namespace Algebra diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index 68388199b41c9..fe44dfcd045fe 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -1215,6 +1215,11 @@ theorem ker_map (f : R →+* S) : rw [MvPolynomial.mem_map_C_iff, RingHom.mem_ker, MvPolynomial.ext_iff] simp_rw [coeff_map, coeff_zero, RingHom.mem_ker] +lemma ker_mapAlgHom {S₁ S₂ σ : Type*} [CommRing S₁] [CommRing S₂] [Algebra R S₁] + [Algebra R S₂] (f : S₁ →ₐ[R] S₂) : + RingHom.ker (MvPolynomial.mapAlgHom (σ := σ) f) = Ideal.map MvPolynomial.C (RingHom.ker f) := + MvPolynomial.ker_map (f.toRingHom : S₁ →+* S₂) + end MvPolynomial section UniqueFactorizationDomain diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index ec8185b2aa0e4..1fbea429322dc 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -27,11 +27,10 @@ A presentation of an `R`-algebra `S` is a distinguished family of generators and - `Algebra.Presentation.dimension`: The dimension of a presentation is the number of generators minus the number of relations. -We also give constructors for localization and base change. +We also give constructors for localization, base change and composition. ## TODO -- Define composition of presentations. - Define `Hom`s of presentations. ## Notes @@ -201,6 +200,8 @@ lemma localizationAway_dimension_zero : (localizationAway r (S := S)).dimension end Localization +section BaseChange + variable (T) [CommRing T] [Algebra R T] (P : Presentation R S) private lemma span_range_relation_eq_ker_baseChange : @@ -266,6 +267,159 @@ instance baseChange_isFinite [P.IsFinite] : (P.baseChange T).IsFinite where finite_vars := inferInstanceAs <| Finite (P.vars) finite_rels := inferInstanceAs <| Finite (P.rels) +end BaseChange + +section Composition + +/-! +### Composition of presentations + +Let `S` be an `R`-algebra with presentation `P` and `T` be an `S`-algebra with +presentation `Q`. In this section we construct a presentation of `T` as an `R`-algebra. + +For the underlying generators see `Algebra.Generators.comp`. The family of relations is +indexed by `Q.rels ⊕ P.rels`. + +We have two canonical maps: +`MvPolynomial P.vars R →ₐ[R] MvPolynomial (Q.vars ⊕ P.vars) R` induced by `Sum.inr` +and `aux : MvPolynomial (Q.vars ⊕ P.vars) R →ₐ[R] MvPolynomial Q.vars S` induced by +the evaluation `MvPolynomial P.vars R →ₐ[R] S` (see below). + +Now `i : P.rels` is mapped to the image of `P.relation i` under the first map and +`j : Q.rels` is mapped to a pre-image under `aux` of `Q.relation j` (see `comp_relation_aux` +for the construction of the pre-image and `comp_relation_aux_map` for a proof that it is indeed +a pre-image). + +The evaluation map factors as: +`MvPolynomial (Q.vars ⊕ P.vars) R →ₐ[R] MvPolynomial Q.vars S →ₐ[R] T`, where +the first map is `aux`. The goal is to compute that the kernel of this composition +is spanned by the relations indexed by `Q.rels ⊕ P.rels` (`span_range_relation_eq_ker_comp`). +One easily sees that this kernel is the pre-image under `aux` of the kernel of the evaluation +of `Q`, where the latter is by assumption spanned by the relations `Q.relation j`. + +Since `aux` is surjective (`aux_surjective`), the pre-image is the sum of the ideal spanned +by the constructed pre-images of the `Q.relation j` and the kernel of `aux`. It hence +remains to show that the kernel of `aux` is spanned by the image of the `P.relation i` +under the canonical map `MvPolynomial P.vars R →ₐ[R] MvPolynomial (Q.vars ⊕ P.vars) R`. By +assumption this span is the kernel of the evaluation map of `P`. For this, we use the isomorphism +`MvPolynomial (Q.vars ⊕ P.vars) R ≃ₐ[R] MvPolynomial Q.vars (MvPolynomial P.vars R)` and +`MvPolynomial.ker_map`. + +-/ + +variable {T} [CommRing T] [Algebra S T] +variable (Q : Presentation S T) (P : Presentation R S) + +/-- The evaluation map `MvPolynomial (Q.vars ⊕ P.vars) →ₐ[R] T` factors via this map. For more +details, see the module docstring at the beginning of the section. -/ +private noncomputable def aux : MvPolynomial (Q.vars ⊕ P.vars) R →ₐ[R] MvPolynomial Q.vars S := + aeval (Sum.elim X (MvPolynomial.C ∘ P.val)) + +/-- A choice of pre-image of `Q.relation r` under `aux`. -/ +private noncomputable def comp_relation_aux (r : Q.rels) : MvPolynomial (Q.vars ⊕ P.vars) R := + Finsupp.sum (Q.relation r) + (fun x j ↦ (MvPolynomial.rename Sum.inr <| P.σ j) * monomial (x.mapDomain Sum.inl) 1) + +@[simp] +private lemma aux_X (i : Q.vars ⊕ P.vars) : (Q.aux P) (X i) = Sum.elim X (C ∘ P.val) i := + aeval_X (Sum.elim X (C ∘ P.val)) i + +/-- The pre-images constructed in `comp_relation_aux` are indeed pre-images under `aux`. -/ +private lemma comp_relation_aux_map (r : Q.rels) : + (Q.aux P) (Q.comp_relation_aux P r) = Q.relation r := by + simp only [aux, comp_relation_aux, Generators.comp_vars, Sum.elim_inl, map_finsupp_sum] + simp only [_root_.map_mul, aeval_rename, aeval_monomial, Sum.elim_comp_inr] + conv_rhs => rw [← Finsupp.sum_single (Q.relation r)] + congr + ext u s m + simp only [MvPolynomial.single_eq_monomial, aeval, AlgHom.coe_mk, coe_eval₂Hom] + rw [monomial_eq, IsScalarTower.algebraMap_eq R S, algebraMap_eq, ← eval₂_comp_left, ← aeval_def] + simp [Finsupp.prod_mapDomain_index_inj (Sum.inl_injective)] + +private lemma aux_surjective : Function.Surjective (Q.aux P) := fun p ↦ by + induction' p using MvPolynomial.induction_on with a p q hp hq p i h + · use rename Sum.inr <| P.σ a + simp only [aux, aeval_rename, Sum.elim_comp_inr] + have (p : MvPolynomial P.vars R) : + aeval (C ∘ P.val) p = (C (aeval P.val p) : MvPolynomial Q.vars S) := by + induction' p using MvPolynomial.induction_on with a p q hp hq p i h + · simp + · simp [hp, hq] + · simp [h] + simp [this] + · obtain ⟨a, rfl⟩ := hp + obtain ⟨b, rfl⟩ := hq + exact ⟨a + b, map_add _ _ _⟩ + · obtain ⟨a, rfl⟩ := h + exact ⟨(a * X (Sum.inl i)), by simp⟩ + +private lemma aux_image_relation : + Q.aux P '' (Set.range (Algebra.Presentation.comp_relation_aux Q P)) = Set.range Q.relation := by + ext x + constructor + · rintro ⟨y, ⟨a, rfl⟩, rfl⟩ + exact ⟨a, (Q.comp_relation_aux_map P a).symm⟩ + · rintro ⟨y, rfl⟩ + use Q.comp_relation_aux P y + simp only [Set.mem_range, exists_apply_eq_apply, true_and, comp_relation_aux_map] + +private lemma aux_eq_comp : Q.aux P = + (MvPolynomial.mapAlgHom (aeval P.val)).comp (sumAlgEquiv R Q.vars P.vars).toAlgHom := by + ext i : 1 + cases i <;> simp + +private lemma aux_ker : + RingHom.ker (Q.aux P) = Ideal.map (rename Sum.inr) (RingHom.ker (aeval P.val)) := by + rw [aux_eq_comp, ← AlgHom.comap_ker, MvPolynomial.ker_mapAlgHom] + show Ideal.comap _ (Ideal.map (IsScalarTower.toAlgHom R (MvPolynomial P.vars R) _) _) = _ + rw [← sumAlgEquiv_comp_rename_inr, ← Ideal.map_mapₐ, Ideal.comap_map_of_bijective] + simpa using AlgEquiv.bijective (sumAlgEquiv R Q.vars P.vars) + +variable [Algebra R T] [IsScalarTower R S T] + +private lemma aeval_comp_val_eq : + (aeval (Q.comp P.toGenerators).val) = + (aevalTower (IsScalarTower.toAlgHom R S T) Q.val).comp (Q.aux P) := by + ext i + simp only [AlgHom.coe_comp, Function.comp_apply] + erw [Q.aux_X P i] + cases i <;> simp + +private lemma span_range_relation_eq_ker_comp : Ideal.span + (Set.range (Sum.elim (Algebra.Presentation.comp_relation_aux Q P) + fun rp ↦ (rename Sum.inr) (P.relation rp))) = (Q.comp P.toGenerators).ker := by + rw [Generators.ker_eq_ker_aeval_val, Q.aeval_comp_val_eq, ← AlgHom.comap_ker] + show _ = Ideal.comap _ (Q.ker) + rw [← Q.span_range_relation_eq_ker, ← Q.aux_image_relation P, ← Ideal.map_span, + Ideal.comap_map_of_surjective' _ (Q.aux_surjective P)] + rw [Set.Sum.elim_range, Ideal.span_union, Q.aux_ker, ← P.ker_eq_ker_aeval_val, + ← P.span_range_relation_eq_ker, Ideal.map_span] + congr + ext + simp + +/-- Given presentations of `T` over `S` and of `S` over `R`, +we may construct a presentation of `T` over `R`. -/ +@[simps rels, simps (config := .lemmasOnly) relation] +noncomputable def comp : Presentation R T where + toGenerators := Q.toGenerators.comp P.toGenerators + rels := Q.rels ⊕ P.rels + relation := Sum.elim (Q.comp_relation_aux P) + (fun rp ↦ MvPolynomial.rename Sum.inr <| P.relation rp) + span_range_relation_eq_ker := Q.span_range_relation_eq_ker_comp P + +lemma comp_relation_map (r : Q.rels) : + aeval (Sum.elim X (MvPolynomial.C ∘ P.val)) ((Q.comp P).relation (Sum.inl r)) = + Q.relation r := by + show (Q.aux P) _ = _ + simp [comp_relation, comp_relation_aux_map] + +instance comp_isFinite [P.IsFinite] [Q.IsFinite] : (Q.comp P).IsFinite where + finite_vars := inferInstanceAs <| Finite (Q.vars ⊕ P.vars) + finite_rels := inferInstanceAs <| Finite (Q.rels ⊕ P.rels) + +end Composition + end Construction end Presentation From de8baaebabba5cd6126829edad19e50dffb345e3 Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Thu, 19 Sep 2024 16:35:30 +0000 Subject: [PATCH 050/170] doc(Order/Interval/Finset): correct typo (#16942) Fix typo in docstring for `lt_iff_transGen_covBy` --- Mathlib/Order/Interval/Finset/Basic.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Order/Interval/Finset/Basic.lean b/Mathlib/Order/Interval/Finset/Basic.lean index 8f54103e53fcc..f47de398e6c28 100644 --- a/Mathlib/Order/Interval/Finset/Basic.lean +++ b/Mathlib/Order/Interval/Finset/Basic.lean @@ -17,7 +17,7 @@ respectively, `⩿` and `⋖`, which then leads to a characterization of monoton functions whose domain is a locally finite order. In particular, this file proves: * `le_iff_transGen_wcovBy`: `≤` is the transitive closure of `⩿` -* `lt_iff_transGen_covBy`: `≤` is the transitive closure of `⩿` +* `lt_iff_transGen_covBy`: `<` is the transitive closure of `⋖` * `monotone_iff_forall_wcovBy`: Characterization of monotone functions * `strictMono_iff_forall_covBy`: Characterization of strictly monotone functions From 84c1496577894f858a4a19cea389f99e062bd9d1 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Jie Rui Date: Thu, 19 Sep 2024 17:19:13 +0000 Subject: [PATCH 051/170] chore: remove `autoImplicit` in `Tactic.Ring.Basic` (#16154) --- Mathlib/Control/Random.lean | 2 +- Mathlib/Tactic/Ring/Basic.lean | 44 +++++++++++++++++++++------------- Mathlib/Tactic/ToExpr.lean | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Mathlib/Control/Random.lean b/Mathlib/Control/Random.lean index 598d03e3d3880..c83ecbaba193b 100644 --- a/Mathlib/Control/Random.lean +++ b/Mathlib/Control/Random.lean @@ -28,7 +28,7 @@ defining objects that can be created randomly. -/ -set_option autoImplicit true +set_option autoImplicit true -- Note: this file uses `autoImplicit` pervasively /-- A monad transformer to generate random objects using the generic generator type `g` -/ abbrev RandGT (g : Type) := StateT (ULift g) diff --git a/Mathlib/Tactic/Ring/Basic.lean b/Mathlib/Tactic/Ring/Basic.lean index bda62f7eef640..459dfa19e288a 100644 --- a/Mathlib/Tactic/Ring/Basic.lean +++ b/Mathlib/Tactic/Ring/Basic.lean @@ -134,26 +134,28 @@ inductive ExSum : ∀ {u : Lean.Level} {α : Q(Type u)}, Q(CommSemiring $α) → ExProd sα a → ExSum sα b → ExSum sα q($a + $b) end - --- In this file, we would like to use multi-character auto-implicits. -set_option autoImplicit true - mutual -- partial only to speed up compilation /-- Equality test for expressions. This is not a `BEq` instance because it is heterogeneous. -/ -partial def ExBase.eq : ExBase sα a → ExBase sα b → Bool +partial def ExBase.eq + {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a b : Q($α)} : + ExBase sα a → ExBase sα b → Bool | .atom i, .atom j => i == j | .sum a, .sum b => a.eq b | _, _ => false @[inherit_doc ExBase.eq] -partial def ExProd.eq : ExProd sα a → ExProd sα b → Bool +partial def ExProd.eq + {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a b : Q($α)} : + ExProd sα a → ExProd sα b → Bool | .const i _, .const j _ => i == j | .mul a₁ a₂ a₃, .mul b₁ b₂ b₃ => a₁.eq b₁ && a₂.eq b₂ && a₃.eq b₃ | _, _ => false @[inherit_doc ExBase.eq] -partial def ExSum.eq : ExSum sα a → ExSum sα b → Bool +partial def ExSum.eq + {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a b : Q($α)} : + ExSum sα a → ExSum sα b → Bool | .zero, .zero => true | .add a₁ a₂, .add b₁ b₂ => a₁.eq b₁ && a₂.eq b₂ | _, _ => false @@ -164,28 +166,34 @@ mutual -- partial only to speed up compilation A total order on normalized expressions. This is not an `Ord` instance because it is heterogeneous. -/ -partial def ExBase.cmp : ExBase sα a → ExBase sα b → Ordering +partial def ExBase.cmp + {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a b : Q($α)} : + ExBase sα a → ExBase sα b → Ordering | .atom i, .atom j => compare i j | .sum a, .sum b => a.cmp b | .atom .., .sum .. => .lt | .sum .., .atom .. => .gt @[inherit_doc ExBase.cmp] -partial def ExProd.cmp : ExProd sα a → ExProd sα b → Ordering +partial def ExProd.cmp + {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a b : Q($α)} : + ExProd sα a → ExProd sα b → Ordering | .const i _, .const j _ => compare i j | .mul a₁ a₂ a₃, .mul b₁ b₂ b₃ => (a₁.cmp b₁).then (a₂.cmp b₂) |>.then (a₃.cmp b₃) | .const _ _, .mul .. => .lt | .mul .., .const _ _ => .gt @[inherit_doc ExBase.cmp] -partial def ExSum.cmp : ExSum sα a → ExSum sα b → Ordering +partial def ExSum.cmp + {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a b : Q($α)} : + ExSum sα a → ExSum sα b → Ordering | .zero, .zero => .eq | .add a₁ a₂, .add b₁ b₂ => (a₁.cmp b₁).then (a₂.cmp b₂) | .zero, .add .. => .lt | .add .., .zero => .gt end -variable {u : Lean.Level} {arg : Q(Type u)} {sα : Q(CommSemiring $arg)} +variable {u : Lean.Level} {α : Q(Type u)} {sα : Q(CommSemiring $α)} instance : Inhabited (Σ e, (ExBase sα) e) := ⟨default, .atom 0⟩ instance : Inhabited (Σ e, (ExSum sα) e) := ⟨_, .zero⟩ @@ -194,24 +202,28 @@ instance : Inhabited (Σ e, (ExProd sα) e) := ⟨default, .const 0 none⟩ mutual /-- Converts `ExBase sα` to `ExBase sβ`, assuming `sα` and `sβ` are defeq. -/ -partial def ExBase.cast {a : Q($arg)} : ExBase sα a → Σ a, ExBase sβ a +partial def ExBase.cast + {v : Lean.Level} {β : Q(Type v)} {sβ : Q(CommSemiring $β)} {a : Q($α)} : + ExBase sα a → Σ a, ExBase sβ a | .atom i => ⟨a, .atom i⟩ | .sum a => let ⟨_, vb⟩ := a.cast; ⟨_, .sum vb⟩ /-- Converts `ExProd sα` to `ExProd sβ`, assuming `sα` and `sβ` are defeq. -/ -partial def ExProd.cast {a : Q($arg)} : ExProd sα a → Σ a, ExProd sβ a +partial def ExProd.cast + {v : Lean.Level} {β : Q(Type v)} {sβ : Q(CommSemiring $β)} {a : Q($α)} : + ExProd sα a → Σ a, ExProd sβ a | .const i h => ⟨a, .const i h⟩ | .mul a₁ a₂ a₃ => ⟨_, .mul a₁.cast.2 a₂ a₃.cast.2⟩ /-- Converts `ExSum sα` to `ExSum sβ`, assuming `sα` and `sβ` are defeq. -/ -partial def ExSum.cast {a : Q($arg)} : ExSum sα a → Σ a, ExSum sβ a +partial def ExSum.cast + {v : Lean.Level} {β : Q(Type v)} {sβ : Q(CommSemiring $β)} {a : Q($α)} : + ExSum sα a → Σ a, ExSum sβ a | .zero => ⟨_, .zero⟩ | .add a₁ a₂ => ⟨_, .add a₁.cast.2 a₂.cast.2⟩ end -set_option autoImplicit false - variable {u : Lean.Level} /-- diff --git a/Mathlib/Tactic/ToExpr.lean b/Mathlib/Tactic/ToExpr.lean index 3c57fb543a3b6..b02e21d2b44bb 100644 --- a/Mathlib/Tactic/ToExpr.lean +++ b/Mathlib/Tactic/ToExpr.lean @@ -16,7 +16,7 @@ that come from core Lean 4 that do not handle universe polymorphism. In addition, we provide some additional `ToExpr` instances for core definitions. -/ -section override +section override -- Note: this section uses `autoImplicit` pervasively namespace Lean attribute [-instance] Lean.instToExprOption From db697686d0b9133f642a5516c4f2d62ee851d6de Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 19 Sep 2024 18:05:57 +0000 Subject: [PATCH 052/170] feat(CategoryTheory/Galois): prerequisites for essential surjectivity (#16948) This PR collects prerequisites for the essential surjectivity of fiber functors in a Galois category. --- Mathlib/CategoryTheory/Galois/Basic.lean | 4 + Mathlib/CategoryTheory/Galois/Examples.lean | 25 ++++-- .../CategoryTheory/Galois/GaloisObjects.lean | 11 +++ .../RepresentationTheory/Action/Basic.lean | 16 ++++ .../RepresentationTheory/Action/Concrete.lean | 84 +++++++++++++++++++ 5 files changed, 134 insertions(+), 6 deletions(-) diff --git a/Mathlib/CategoryTheory/Galois/Basic.lean b/Mathlib/CategoryTheory/Galois/Basic.lean index 1c84616fff5ed..70049a038bcc4 100644 --- a/Mathlib/CategoryTheory/Galois/Basic.lean +++ b/Mathlib/CategoryTheory/Galois/Basic.lean @@ -191,6 +191,10 @@ lemma mulAction_def {X : C} (σ : Aut F) (x : F.obj X) : σ • x = σ.hom.app X x := rfl +lemma mulAction_naturality {X Y : C} (σ : Aut F) (f : X ⟶ Y) (x : F.obj X) : + σ • F.map f x = F.map f (σ • x) := + FunctorToFintypeCat.naturality F F σ.hom f x + /-- An object that is neither initial or connected has a non-trivial subobject. -/ lemma has_non_trivial_subobject_of_not_isConnected_of_not_initial (X : C) (hc : ¬ IsConnected X) (hi : IsInitial X → False) : diff --git a/Mathlib/CategoryTheory/Galois/Examples.lean b/Mathlib/CategoryTheory/Galois/Examples.lean index f98bc024d2dde..a3bbd1400e05c 100644 --- a/Mathlib/CategoryTheory/Galois/Examples.lean +++ b/Mathlib/CategoryTheory/Galois/Examples.lean @@ -4,12 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Christian Merten -/ import Mathlib.CategoryTheory.Galois.Basic -import Mathlib.RepresentationTheory.Action.Basic import Mathlib.RepresentationTheory.Action.Concrete import Mathlib.RepresentationTheory.Action.Limits -import Mathlib.CategoryTheory.Limits.FintypeCat -import Mathlib.CategoryTheory.Limits.Shapes.Types -import Mathlib.Logic.Equiv.TransferInstance /-! # Examples of Galois categories and fiber functors @@ -25,10 +21,10 @@ universe u v w namespace CategoryTheory -namespace FintypeCat - open Limits Functor PreGaloisCategory +namespace FintypeCat + /-- Complement of the image of a morphism `f : X ⟶ Y` in `FintypeCat`. -/ noncomputable def imageComplement {X Y : FintypeCat.{u}} (f : X ⟶ Y) : FintypeCat.{u} := by @@ -153,6 +149,23 @@ theorem Action.isConnected_iff_transitive (X : Action FintypeCat (MonCat.of G)) IsConnected X ↔ MulAction.IsPretransitive G X.V := ⟨fun _ ↦ pretransitive_of_isConnected G X, fun _ ↦ isConnected_of_transitive G X.V⟩ +variable {G} + +/-- If `X` is a connected `G`-set and `x` is an element of `X`, `X` is isomorphic +to the quotient of `G` by the stabilizer of `x` as `G`-sets. -/ +noncomputable def isoQuotientStabilizerOfIsConnected (X : Action FintypeCat (MonCat.of G)) + [IsConnected X] (x : X.V) [Fintype (G ⧸ (MulAction.stabilizer G x))] : + X ≅ G ⧸ₐ MulAction.stabilizer G x := + haveI : MulAction.IsPretransitive G X.V := Action.pretransitive_of_isConnected G X + let e : X.V ≃ G ⧸ MulAction.stabilizer G x := + (Equiv.Set.univ X.V).symm.trans <| + (Equiv.setCongr ((MulAction.orbit_eq_univ G x).symm)).trans <| + MulAction.orbitEquivQuotientStabilizer G x + Iso.symm <| Action.mkIso (FintypeCat.equivEquivIso e.symm) <| fun σ : G ↦ by + ext (a : G ⧸ MulAction.stabilizer G x) + obtain ⟨τ, rfl⟩ := Quotient.exists_rep a + exact mul_smul σ τ x + end FintypeCat end CategoryTheory diff --git a/Mathlib/CategoryTheory/Galois/GaloisObjects.lean b/Mathlib/CategoryTheory/Galois/GaloisObjects.lean index 1f1435877b5a6..25fbc42d60592 100644 --- a/Mathlib/CategoryTheory/Galois/GaloisObjects.lean +++ b/Mathlib/CategoryTheory/Galois/GaloisObjects.lean @@ -95,6 +95,17 @@ instance isPretransitive_of_isGalois (X : C) [IsGalois X] : rw [← isGalois_iff_pretransitive] infer_instance +lemma stabilizer_normal_of_isGalois (X : C) [IsGalois X] (x : F.obj X) : + Subgroup.Normal (MulAction.stabilizer (Aut F) x) where + conj_mem n ninstab g := by + rw [MulAction.mem_stabilizer_iff] + show g • n • (g⁻¹ • x) = x + have : ∃ (φ : Aut X), F.map φ.hom x = g⁻¹ • x := + MulAction.IsPretransitive.exists_smul_eq x (g⁻¹ • x) + obtain ⟨φ, h⟩ := this + rw [← h, mulAction_naturality, ninstab, h] + simp + theorem evaluation_aut_surjective_of_isGalois (A : C) [IsGalois A] (a : F.obj A) : Function.Surjective (fun f : Aut A ↦ F.map f.hom a) := MulAction.IsPretransitive.exists_smul_eq a diff --git a/Mathlib/RepresentationTheory/Action/Basic.lean b/Mathlib/RepresentationTheory/Action/Basic.lean index f52d5604cf170..7f3481318aa92 100644 --- a/Mathlib/RepresentationTheory/Action/Basic.lean +++ b/Mathlib/RepresentationTheory/Action/Basic.lean @@ -125,6 +125,16 @@ theorem comp_hom {M N K : Action V G} (f : M ⟶ N) (g : N ⟶ K) : (f ≫ g : Hom M K).hom = f.hom ≫ g.hom := rfl +@[simp] +theorem hom_inv_hom {M N : Action V G} (f : M ≅ N) : + f.hom.hom ≫ f.inv.hom = 𝟙 M.V := by + rw [← comp_hom, Iso.hom_inv_id, id_hom] + +@[simp] +theorem inv_hom_hom {M N : Action V G} (f : M ≅ N) : + f.inv.hom ≫ f.hom.hom = 𝟙 N.V := by + rw [← comp_hom, Iso.inv_hom_id, id_hom] + /-- Construct an isomorphism of `G` actions/representations from an isomorphism of the underlying objects, where the forward direction commutes with the group action. -/ @@ -145,6 +155,12 @@ instance isIso_hom_mk {M N : Action V G} (f : M.V ⟶ N.V) [IsIso f] (w) : @IsIso _ _ M N (Hom.mk f w) := (mkIso (asIso f) w).isIso_hom +instance {M N : Action V G} (f : M ≅ N) : IsIso f.hom.hom where + out := ⟨f.inv.hom, by simp⟩ + +instance {M N : Action V G} (f : M ≅ N) : IsIso f.inv.hom where + out := ⟨f.hom.hom, by simp⟩ + namespace FunctorCategoryEquivalence /-- Auxiliary definition for `functorCategoryEquivalence`. -/ diff --git a/Mathlib/RepresentationTheory/Action/Concrete.lean b/Mathlib/RepresentationTheory/Action/Concrete.lean index 1ae786bb201e9..3c2ec6686bc7d 100644 --- a/Mathlib/RepresentationTheory/Action/Concrete.lean +++ b/Mathlib/RepresentationTheory/Action/Concrete.lean @@ -5,6 +5,8 @@ Authors: Scott Morrison -/ import Mathlib.Algebra.Group.Action.Pi import Mathlib.CategoryTheory.FintypeCat +import Mathlib.GroupTheory.GroupAction.Quotient +import Mathlib.GroupTheory.QuotientGroup.Basic import Mathlib.RepresentationTheory.Action.Basic /-! @@ -68,6 +70,12 @@ def diagonalOneIsoLeftRegular (G : Type u) [Monoid G] : diagonal G 1 ≅ leftReg namespace FintypeCat +/-- If `X` is a type with `[Fintype X]` and `G` acts on `X`, then `G` also acts on +`FintypeCat.of X`. -/ +instance (G : Type*) (X : Type*) [Monoid G] [MulAction G X] [Fintype X] : + MulAction G (FintypeCat.of X) := + inferInstanceAs <| MulAction G X + /-- Bundles a finite type `H` with a multiplicative action of `G` as an `Action`. -/ def ofMulAction (G : Type u) (H : FintypeCat.{u}) [Monoid G] [MulAction G H] : Action FintypeCat (MonCat.of G) where @@ -79,6 +87,82 @@ theorem ofMulAction_apply {G : Type u} {H : FintypeCat.{u}} [Monoid G] [MulActio (g : G) (x : H) : (FintypeCat.ofMulAction G H).ρ g x = (g • x : H) := rfl +section + +/-- Shorthand notation for the quotient of `G` by `H` as a finite `G`-set. -/ +notation:10 G:10 " ⧸ₐ " H:10 => Action.FintypeCat.ofMulAction G (FintypeCat.of <| G ⧸ H) + +variable {G : Type*} [Group G] (H N : Subgroup G) [Fintype (G ⧸ N)] + +/-- If `N` is a normal subgroup of `G`, then this is the group homomorphism +sending an element `g` of `G` to the `G`-endomorphism of `G ⧸ₐ N` given by +multiplication with `g⁻¹` on the right. -/ +def toEndHom [N.Normal] : G →* End (G ⧸ₐ N) where + toFun v := { + hom := Quotient.lift (fun σ ↦ ⟦σ * v⁻¹⟧) <| fun a b h ↦ Quotient.sound <| by + apply (QuotientGroup.leftRel_apply).mpr + simp only [mul_inv_rev, inv_inv] + convert_to v * (a⁻¹ * b) * v⁻¹ ∈ N + · group + · exact Subgroup.Normal.conj_mem ‹_› _ (QuotientGroup.leftRel_apply.mp h) _ + comm := fun (g : G) ↦ by + ext (x : G ⧸ N) + induction' x using Quotient.inductionOn with x + simp only [FintypeCat.comp_apply, Action.FintypeCat.ofMulAction_apply, Quotient.lift_mk] + show Quotient.lift (fun σ ↦ ⟦σ * v⁻¹⟧) _ (⟦g • x⟧) = _ + simp only [smul_eq_mul, Quotient.lift_mk, mul_assoc] + rfl + } + map_one' := by + apply Action.hom_ext + ext (x : G ⧸ N) + induction' x using Quotient.inductionOn with x + simp + map_mul' σ τ := by + apply Action.hom_ext + ext (x : G ⧸ N) + induction' x using Quotient.inductionOn with x + show ⟦x * (σ * τ)⁻¹⟧ = ⟦x * τ⁻¹ * σ⁻¹⟧ + rw [mul_inv_rev, mul_assoc] + +@[simp] +lemma toEndHom_apply [N.Normal] (g h : G) : (toEndHom N g).hom ⟦h⟧ = ⟦h * g⁻¹⟧ := rfl + +variable {N} in +lemma toEndHom_trivial_of_mem [N.Normal] {n : G} (hn : n ∈ N) : toEndHom N n = 𝟙 (G ⧸ₐ N) := by + apply Action.hom_ext + ext (x : G ⧸ N) + induction' x using Quotient.inductionOn with μ + exact Quotient.sound ((QuotientGroup.leftRel_apply).mpr <| by simpa) + +/-- If `H` and `N` are subgroups of a group `G` with `N` normal, there is a canonical +group homomorphism `H ⧸ N ⊓ H` to the `G`-endomorphisms of `G ⧸ N`. -/ +def quotientToEndHom [N.Normal] : H ⧸ Subgroup.subgroupOf N H →* End (G ⧸ₐ N) := + QuotientGroup.lift (Subgroup.subgroupOf N H) ((toEndHom N).comp H.subtype) <| fun _ uinU' ↦ + toEndHom_trivial_of_mem uinU' + +@[simp] +lemma quotientToEndHom_mk [N.Normal] (x : H) (g : G) : + (quotientToEndHom H N ⟦x⟧).hom ⟦g⟧ = ⟦g * x⁻¹⟧ := + rfl + +/-- If `N` and `H` are subgroups of a group `G` with `N ≤ H`, this is the canonical +`G`-morphism `G ⧸ N ⟶ G ⧸ H`. -/ +def quotientToQuotientOfLE [Fintype (G ⧸ H)] (h : N ≤ H) : (G ⧸ₐ N) ⟶ (G ⧸ₐ H) where + hom := Quotient.lift _ <| fun a b hab ↦ Quotient.sound <| + (QuotientGroup.leftRel_apply).mpr (h <| (QuotientGroup.leftRel_apply).mp hab) + comm g := by + ext (x : G ⧸ N) + induction' x using Quotient.inductionOn with μ + rfl + +@[simp] +lemma quotientToQuotientOfLE_hom_mk [Fintype (G ⧸ H)] (h : N ≤ H) (x : G) : + (quotientToQuotientOfLE H N h).hom ⟦x⟧ = ⟦x⟧ := + rfl + +end + end FintypeCat section ToMulAction From f71d1808090fc3f4534edd47b50575b1c121e741 Mon Sep 17 00:00:00 2001 From: David Kurniadi Angdinata Date: Thu, 19 Sep 2024 18:18:21 +0000 Subject: [PATCH 053/170] feat(AlgebraicGeometry/EllipticCurve/Projective): implement group operation polynomials for projective coordinates (#9417) Define auxiliary polynomials for the secant-and-tangent negation `neg` and addition `add` on `Fin 3 -> F`. Note that the group operations are defined from scratch instead of pulling back the group operations from the affine case, as this will be more convenient for rewriting and allows them to be defined over a ring. I don't see an easy way to define an analogous `slope` function as in `Affine` when there are now `Z`-coordinates in the polynomials. This is the second in a series of four PRs leading to #8485 --- .../EllipticCurve/Projective.lean | 729 +++++++++++++++++- 1 file changed, 723 insertions(+), 6 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean index e010653a6a29e..1c20ec00d569e 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.MvPolynomial.CommRing import Mathlib.Algebra.MvPolynomial.PDeriv import Mathlib.AlgebraicGeometry.EllipticCurve.Affine import Mathlib.Data.Fin.Tuple.Reflection +import Mathlib.Tactic.LinearCombination' /-! # Projective coordinates for Weierstrass curves @@ -28,6 +29,10 @@ derivatives are independent of the representative for $[x:y:z]$, and the nonsing already implies that $(x, y, z) \ne (0, 0, 0)$, so a nonsingular rational point on `W` can simply be given by a tuple consisting of $[x:y:z]$ and the nonsingular condition on any representative. +As in `Mathlib.AlgebraicGeometry.EllipticCurve.Affine`, the set of nonsingular rational points forms +an abelian group under the same secant-and-tangent process, but the polynomials involved are +homogeneous, and any instances of division become multiplication in the $Z$-coordinate. + ## Main definitions * `WeierstrassCurve.Projective.PointClass`: the equivalence class of a point representative. @@ -105,8 +110,8 @@ lemma fin3_def (P : Fin 3 → R) : ![P x, P y, P z] = P := by lemma fin3_def_ext (X Y Z : R) : ![X, Y, Z] x = X ∧ ![X, Y, Z] y = Y ∧ ![X, Y, Z] z = Z := ⟨rfl, rfl, rfl⟩ -lemma comp_fin3 {S} (f : R → S) (X Y Z : R) : f ∘ ![X, Y, Z] = ![f X, f Y, f Z] := - (FinVec.map_eq _ _).symm +lemma comp_fin3 {S : Type v} (f : R → S) (X Y Z : R) : f ∘ ![X, Y, Z] = ![f X, f Y, f Z] := + (FinVec.map_eq ..).symm variable [CommRing R] @@ -235,10 +240,10 @@ lemma equation_iff (P : Fin 3 → R) : W'.Equation P ↔ rw [Equation, eval_polynomial, sub_eq_zero] lemma equation_smul (P : Fin 3 → R) {u : R} (hu : IsUnit u) : W'.Equation (u • P) ↔ W'.Equation P := - have (u : R) {P : Fin 3 → R} (hP : W'.Equation P) : W'.Equation <| u • P := by + have hP (u : R) {P : Fin 3 → R} (hP : W'.Equation P) : W'.Equation <| u • P := by rw [equation_iff] at hP ⊢ linear_combination (norm := (simp only [smul_fin3_ext]; ring1)) u ^ 3 * hP - ⟨fun h => by convert this hu.unit.inv h; erw [smul_smul, hu.val_inv_mul, one_smul], this u⟩ + ⟨fun h => by convert hP hu.unit.inv h; erw [smul_smul, hu.val_inv_mul, one_smul], hP u⟩ lemma equation_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : W'.Equation P ↔ W'.Equation Q := by rcases h with ⟨u, rfl⟩ @@ -355,7 +360,7 @@ lemma nonsingular_iff (P : Fin 3 → R) : W'.Nonsingular P ↔ W'.Equation P ∧ lemma nonsingular_smul (P : Fin 3 → R) {u : R} (hu : IsUnit u) : W'.Nonsingular (u • P) ↔ W'.Nonsingular P := - have {u : R} (hu : IsUnit u) {P : Fin 3 → R} (hP : W'.Nonsingular <| u • P) : + have hP {u : R} (hu : IsUnit u) {P : Fin 3 → R} (hP : W'.Nonsingular <| u • P) : W'.Nonsingular P := by rcases (nonsingular_iff _).mp hP with ⟨hP, hP'⟩ refine (nonsingular_iff P).mpr ⟨(equation_smul P hu).mp hP, ?_⟩ @@ -364,7 +369,7 @@ lemma nonsingular_smul (P : Fin 3 → R) {u : R} (hu : IsUnit u) : exact ⟨by linear_combination (norm := ring1) u ^ 2 * hP'.left, by linear_combination (norm := ring1) u ^ 2 * hP'.right.left, by linear_combination (norm := ring1) u ^ 2 * hP'.right.right⟩ - ⟨this hu, fun h => this hu.unit⁻¹.isUnit <| by rwa [smul_smul, hu.val_inv_mul, one_smul]⟩ + ⟨hP hu, fun h => hP hu.unit⁻¹.isUnit <| by rwa [smul_smul, hu.val_inv_mul, one_smul]⟩ lemma nonsingular_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : W'.Nonsingular P ↔ W'.Nonsingular Q := by rcases h with ⟨u, rfl⟩ @@ -446,4 +451,716 @@ alias nonsingular_of_affine_of_Z_ne_zero := nonsingular_of_Z_ne_zero @[deprecated (since := "2024-08-27")] alias nonsingular_smul_iff := nonsingular_smul @[deprecated (since := "2024-08-27")] alias nonsingular_zero' := nonsingular_zero +section Negation + +/-! ### Negation formulae -/ + +variable (W') in +/-- The $Y$-coordinate of a representative of `-P` for a point `P`. -/ +def negY (P : Fin 3 → R) : R := + -P y - W'.a₁ * P x - W'.a₃ * P z + +lemma negY_eq (X Y Z : R) : W'.negY ![X, Y, Z] = -Y - W'.a₁ * X - W'.a₃ * Z := + rfl + +lemma negY_smul (P : Fin 3 → R) (u : R) : W'.negY (u • P) = u * W'.negY P := by + simp only [negY, smul_fin3_ext] + ring1 + +lemma negY_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Equation P) (hPz : P z = 0) : + W'.negY P = -P y := by + rw [negY, hPz, X_eq_zero_of_Z_eq_zero hP hPz, mul_zero, sub_zero, mul_zero, sub_zero] + +lemma negY_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : + W.negY P / P z = W.toAffine.negY (P x / P z) (P y / P z) := by + linear_combination (norm := (rw [negY, Affine.negY]; ring1)) -W.a₃ * div_self hPz + +lemma Y_sub_Y_mul_Y_sub_negY {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hx : P x * Q z = Q x * P z) : + P z * Q z * (P y * Q z - Q y * P z) * (P y * Q z - W'.negY Q * P z) = 0 := by + linear_combination' (norm := (rw [negY]; ring1)) Q z ^ 3 * (equation_iff P).mp hP + - P z ^ 3 * (equation_iff Q).mp hQ + hx * hx * hx + W'.a₂ * P z * Q z * hx * hx + + (W'.a₄ * P z ^ 2 * Q z ^ 2 - W'.a₁ * P y * P z * Q z ^ 2) * hx + +lemma Y_eq_of_Y_ne [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ Q y * P z) : + P y * Q z = W'.negY Q * P z := + sub_eq_zero.mp <| (mul_eq_zero.mp <| Y_sub_Y_mul_Y_sub_negY hP hQ hx).resolve_left <| + mul_ne_zero (mul_ne_zero hPz hQz) <| sub_ne_zero.mpr hy + +lemma Y_eq_of_Y_ne' [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) + (hy : P y * Q z ≠ W'.negY Q * P z) : P y * Q z = Q y * P z := + sub_eq_zero.mp <| (mul_eq_zero.mp <| (mul_eq_zero.mp <| Y_sub_Y_mul_Y_sub_negY hP hQ hx + ).resolve_right <| sub_ne_zero.mpr hy).resolve_left <| mul_ne_zero hPz hQz + +lemma Y_eq_iff' {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) : + P y * Q z = W.negY Q * P z ↔ P y / P z = W.toAffine.negY (Q x / Q z) (Q y / Q z) := + negY_of_Z_ne_zero hQz ▸ (div_eq_div_iff hPz hQz).symm + +lemma Y_sub_Y_add_Y_sub_negY {P Q : Fin 3 → R} (hx : P x * Q z = Q x * P z) : + (P y * Q z - Q y * P z) + (P y * Q z - W'.negY Q * P z) = (P y - W'.negY P) * Q z := by + linear_combination (norm := (rw [negY, negY]; ring1)) -W'.a₁ * hx + +lemma Y_ne_negY_of_Y_ne [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hQ : W'.Equation Q) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) + (hy : P y * Q z ≠ Q y * P z) : P y ≠ W'.negY P := by + have hy' : P y * Q z - W'.negY Q * P z = 0 := sub_eq_zero.mpr <| Y_eq_of_Y_ne hP hQ hPz hQz hx hy + contrapose! hy + linear_combination (norm := ring1) Y_sub_Y_add_Y_sub_negY hx + Q z * hy - hy' + +lemma Y_ne_negY_of_Y_ne' [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hQ : W'.Equation Q) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) + (hy : P y * Q z ≠ W'.negY Q * P z) : P y ≠ W'.negY P := by + have hy' : P y * Q z - Q y * P z = 0 := sub_eq_zero.mpr <| Y_eq_of_Y_ne' hP hQ hPz hQz hx hy + contrapose! hy + linear_combination (norm := ring1) Y_sub_Y_add_Y_sub_negY hx + Q z * hy - hy' + +lemma Y_eq_negY_of_Y_eq [NoZeroDivisors R] {P Q : Fin 3 → R} (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W'.negY Q * P z) : + P y = W'.negY P := + mul_left_injective₀ hQz <| by + linear_combination (norm := ring1) -Y_sub_Y_add_Y_sub_negY hx + hy + hy' + +lemma nonsingular_iff_of_Y_eq_negY {P : Fin 3 → F} (hPz : P z ≠ 0) (hy : P y = W.negY P) : + W.Nonsingular P ↔ W.Equation P ∧ eval P W.polynomialX ≠ 0 := by + have hy' : eval P W.polynomialY = (P y - W.negY P) * P z := by rw [negY, eval_polynomialY]; ring1 + rw [nonsingular_iff_of_Z_ne_zero hPz, hy', hy, sub_self, zero_mul, ne_self_iff_false, or_false] + +end Negation + +section Doubling + +/-! ### Doubling formulae -/ + +variable (W) in +/-- The unit associated to the doubling of a 2-torsion point `P`. +More specifically, the unit `u` such that `W.add P P = u • ![0, 1, 0]` where `P = W.neg P`. -/ +noncomputable def dblU (P : Fin 3 → F) : F := + eval P W.polynomialX ^ 3 / P z ^ 2 + +lemma dblU_eq (P : Fin 3 → F) : W.dblU P = + (W.a₁ * P y * P z - (3 * P x ^ 2 + 2 * W.a₂ * P x * P z + W.a₄ * P z ^ 2)) ^ 3 / P z ^ 2 := by + rw [dblU, eval_polynomialX] + +lemma dblU_smul {P : Fin 3 → F} (hPz : P z ≠ 0) {u : F} (hu : u ≠ 0) : + W.dblU (u • P) = u ^ 4 * W.dblU P := by + field_simp [dblU_eq, smul_fin3_ext] + ring1 + +lemma dblU_of_Z_eq_zero {P : Fin 3 → F} (hPz : P z = 0) : W.dblU P = 0 := by + rw [dblU_eq, hPz, zero_pow two_ne_zero, div_zero] + +lemma dblU_ne_zero_of_Y_eq {P Q : Fin 3 → F} (hP : W.Nonsingular P) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W.negY Q * P z) : + W.dblU P ≠ 0 := + div_ne_zero (pow_ne_zero 3 + ((nonsingular_iff_of_Y_eq_negY hPz <| Y_eq_negY_of_Y_eq hQz hx hy hy').mp hP).right) <| + pow_ne_zero 2 hPz + +lemma isUnit_dblU_of_Y_eq {P Q : Fin 3 → F} (hP : W.Nonsingular P) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W.negY Q * P z) : + IsUnit (W.dblU P) := + (dblU_ne_zero_of_Y_eq hP hPz hQz hx hy hy').isUnit + +variable (W') in +/-- The $Z$-coordinate of a representative of `2 • P` for a point `P`. -/ +def dblZ (P : Fin 3 → R) : R := + P z * (P y - W'.negY P) ^ 3 + +lemma dblZ_smul (P : Fin 3 → R) (u : R) : W'.dblZ (u • P) = u ^ 4 * W'.dblZ P := by + simp only [dblZ, negY_smul, smul_fin3_ext] + ring1 + +lemma dblZ_of_Z_eq_zero {P : Fin 3 → R} (hPz : P z = 0) : W'.dblZ P = 0 := by + rw [dblZ, hPz, zero_mul] + +lemma dblZ_of_Y_eq [NoZeroDivisors R] {P Q : Fin 3 → R} (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) + (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W'.negY Q * P z) : W'.dblZ P = 0 := by + rw [dblZ, Y_eq_negY_of_Y_eq hQz hx hy hy', sub_self, zero_pow three_ne_zero, mul_zero] + +lemma dblZ_ne_zero_of_Y_ne [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hQ : W'.Equation Q) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) + (hy : P y * Q z ≠ Q y * P z) : W'.dblZ P ≠ 0 := + mul_ne_zero hPz <| pow_ne_zero 3 <| sub_ne_zero.mpr <| Y_ne_negY_of_Y_ne hP hQ hPz hQz hx hy + +lemma isUnit_dblZ_of_Y_ne {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ Q y * P z) : IsUnit (W.dblZ P) := + (dblZ_ne_zero_of_Y_ne hP hQ hPz hQz hx hy).isUnit + +lemma dblZ_ne_zero_of_Y_ne' [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hQ : W'.Equation Q) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) + (hy : P y * Q z ≠ W'.negY Q * P z) : W'.dblZ P ≠ 0 := + mul_ne_zero hPz <| pow_ne_zero 3 <| sub_ne_zero.mpr <| Y_ne_negY_of_Y_ne' hP hQ hPz hQz hx hy + +lemma isUnit_dblZ_of_Y_ne' {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ W.negY Q * P z) : + IsUnit (W.dblZ P) := + (dblZ_ne_zero_of_Y_ne' hP hQ hPz hQz hx hy).isUnit + +private lemma toAffine_slope_of_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ W.negY Q * P z) : + W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z) = + -eval P W.polynomialX / P z / (P y - W.negY P) := by + have hPy : P y - W.negY P ≠ 0 := sub_ne_zero.mpr <| Y_ne_negY_of_Y_ne' hP hQ hPz hQz hx hy + simp only [X_eq_iff hPz hQz, ne_eq, Y_eq_iff' hPz hQz] at hx hy + rw [Affine.slope_of_Y_ne hx <| negY_of_Z_ne_zero hQz ▸ hy, ← negY_of_Z_ne_zero hPz] + field_simp [eval_polynomialX, hPz] + ring1 + +variable (W') in +/-- The $X$-coordinate of a representative of `2 • P` for a point `P`. -/ +noncomputable def dblX (P : Fin 3 → R) : R := + 2 * P x * P y ^ 3 + 3 * W'.a₁ * P x ^ 2 * P y ^ 2 + 6 * W'.a₂ * P x ^ 3 * P y + - 8 * W'.a₂ * P y ^ 3 * P z + 9 * W'.a₃ * P x ^ 4 - 6 * W'.a₃ * P x * P y ^ 2 * P z + - 6 * W'.a₄ * P x ^ 2 * P y * P z - 18 * W'.a₆ * P x * P y * P z ^ 2 + + 3 * W'.a₁ ^ 2 * P x ^ 3 * P y - 2 * W'.a₁ ^ 2 * P y ^ 3 * P z + 3 * W'.a₁ * W'.a₂ * P x ^ 4 + - 12 * W'.a₁ * W'.a₂ * P x * P y ^ 2 * P z - 9 * W'.a₁ * W'.a₃ * P x ^ 2 * P y * P z + - 3 * W'.a₁ * W'.a₄ * P x ^ 3 * P z - 9 * W'.a₁ * W'.a₆ * P x ^ 2 * P z ^ 2 + + 8 * W'.a₂ ^ 2 * P x ^ 2 * P y * P z + 12 * W'.a₂ * W'.a₃ * P x ^ 3 * P z + - 12 * W'.a₂ * W'.a₃ * P y ^ 2 * P z ^ 2 + 8 * W'.a₂ * W'.a₄ * P x * P y * P z ^ 2 + - 12 * W'.a₃ ^ 2 * P x * P y * P z ^ 2 + 6 * W'.a₃ * W'.a₄ * P x ^ 2 * P z ^ 2 + + 2 * W'.a₄ ^ 2 * P y * P z ^ 3 + W'.a₁ ^ 3 * P x ^ 4 - 3 * W'.a₁ ^ 3 * P x * P y ^ 2 * P z + - 2 * W'.a₁ ^ 2 * W'.a₂ * P x ^ 2 * P y * P z - 3 * W'.a₁ ^ 2 * W'.a₃ * P y ^ 2 * P z ^ 2 + + 2 * W'.a₁ ^ 2 * W'.a₄ * P x * P y * P z ^ 2 + 4 * W'.a₁ * W'.a₂ ^ 2 * P x ^ 3 * P z + - 8 * W'.a₁ * W'.a₂ * W'.a₃ * P x * P y * P z ^ 2 + + 4 * W'.a₁ * W'.a₂ * W'.a₄ * P x ^ 2 * P z ^ 2 - 3 * W'.a₁ * W'.a₃ ^ 2 * P x ^ 2 * P z ^ 2 + + 2 * W'.a₁ * W'.a₃ * W'.a₄ * P y * P z ^ 3 + W'.a₁ * W'.a₄ ^ 2 * P x * P z ^ 3 + + 4 * W'.a₂ ^ 2 * W'.a₃ * P x ^ 2 * P z ^ 2 - 6 * W'.a₂ * W'.a₃ ^ 2 * P y * P z ^ 3 + + 4 * W'.a₂ * W'.a₃ * W'.a₄ * P x * P z ^ 3 - 2 * W'.a₃ ^ 3 * P x * P z ^ 3 + + W'.a₃ * W'.a₄ ^ 2 * P z ^ 4 - W'.a₁ ^ 4 * P x ^ 2 * P y * P z + + W'.a₁ ^ 3 * W'.a₂ * P x ^ 3 * P z - 2 * W'.a₁ ^ 3 * W'.a₃ * P x * P y * P z ^ 2 + + W'.a₁ ^ 3 * W'.a₄ * P x ^ 2 * P z ^ 2 + W'.a₁ ^ 2 * W'.a₂ * W'.a₃ * P x ^ 2 * P z ^ 2 + - W'.a₁ ^ 2 * W'.a₃ ^ 2 * P y * P z ^ 3 + 2 * W'.a₁ ^ 2 * W'.a₃ * W'.a₄ * P x * P z ^ 3 + - W'.a₁ * W'.a₂ * W'.a₃ ^ 2 * P x * P z ^ 3 - W'.a₂ * W'.a₃ ^ 3 * P z ^ 4 + + W'.a₁ * W'.a₃ ^ 2 * W'.a₄ * P z ^ 4 + +lemma dblX_eq' {P : Fin 3 → R} (hP : W'.Equation P) : W'.dblX P * P z = + (eval P W'.polynomialX ^ 2 - W'.a₁ * eval P W'.polynomialX * P z * (P y - W'.negY P) + - W'.a₂ * P z ^ 2 * (P y - W'.negY P) ^ 2 - 2 * P x * P z * (P y - W'.negY P) ^ 2) + * (P y - W'.negY P) := by + linear_combination (norm := (rw [dblX, eval_polynomialX, negY]; ring1)) + 9 * (W'.a₁ * P x ^ 2 + 2 * P x * P y) * (equation_iff _).mp hP + +lemma dblX_eq {P : Fin 3 → F} (hP : W.Equation P) (hPz : P z ≠ 0) : W.dblX P = + ((eval P W.polynomialX ^ 2 - W.a₁ * eval P W.polynomialX * P z * (P y - W.negY P) + - W.a₂ * P z ^ 2 * (P y - W.negY P) ^ 2 - 2 * P x * P z * (P y - W.negY P) ^ 2) + * (P y - W.negY P)) / P z := by + rw [← dblX_eq' hP, mul_div_cancel_right₀ _ hPz] + +lemma dblX_smul (P : Fin 3 → R) (u : R) : W'.dblX (u • P) = u ^ 4 * W'.dblX P := by + simp only [dblX, smul_fin3_ext] + ring1 + +lemma dblX_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Equation P) (hPz : P z = 0) : + W'.dblX P = 0 := by + rw [dblX, hPz, X_eq_zero_of_Z_eq_zero hP hPz] + ring1 + +lemma dblX_of_Y_eq [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) + (hy' : P y * Q z = W'.negY Q * P z) : W'.dblX P = 0 := by + apply eq_zero_of_ne_zero_of_mul_right_eq_zero hPz + rw [dblX_eq' hP, Y_eq_negY_of_Y_eq hQz hx hy hy'] + ring1 + +private lemma toAffine_addX_of_eq {P : Fin 3 → F} (hPz : P z ≠ 0) {n d : F} (hd : d ≠ 0) : + W.toAffine.addX (P x / P z) (P x / P z) (-n / P z / d) = + (n ^ 2 - W.a₁ * n * P z * d - W.a₂ * P z ^ 2 * d ^ 2 - 2 * P x * P z * d ^ 2) * d / P z + / (P z * d ^ 3) := by + field_simp [mul_ne_zero hPz hd] + ring1 + +lemma dblX_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ W.negY Q * P z) : + W.dblX P / W.dblZ P = W.toAffine.addX (P x / P z) (Q x / Q z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)) := by + rw [dblX_eq hP hPz, dblZ, toAffine_slope_of_eq hP hQ hPz hQz hx hy, ← (X_eq_iff hPz hQz).mp hx, + toAffine_addX_of_eq hPz <| sub_ne_zero.mpr <| Y_ne_negY_of_Y_ne' hP hQ hPz hQz hx hy] + +variable (W') in +/-- The $Y$-coordinate of a representative of `-(2 • P)` for a point `P`. -/ +noncomputable def negDblY (P : Fin 3 → R) : R := + -P y ^ 4 - 3 * W'.a₁ * P x * P y ^ 3 - 9 * W'.a₃ * P x ^ 3 * P y + 3 * W'.a₃ * P y ^ 3 * P z + - 3 * W'.a₄ * P x * P y ^ 2 * P z - 27 * W'.a₆ * P x ^ 3 * P z + 9 * W'.a₆ * P y ^ 2 * P z ^ 2 + - 3 * W'.a₁ ^ 2 * P x ^ 2 * P y ^ 2 + 4 * W'.a₁ * W'.a₂ * P y ^ 3 * P z + - 3 * W'.a₁ * W'.a₂ * P x ^ 3 * P y - 9 * W'.a₁ * W'.a₃ * P x ^ 4 + + 6 * W'.a₁ * W'.a₃ * P x * P y ^ 2 * P z + 18 * W'.a₁ * W'.a₆ * P x * P y * P z ^ 2 + + 9 * W'.a₂ ^ 2 * P x ^ 4 - 8 * W'.a₂ ^ 2 * P x * P y ^ 2 * P z + - 9 * W'.a₂ * W'.a₃ * P x ^ 2 * P y * P z + 9 * W'.a₂ * W'.a₄ * P x ^ 3 * P z + - 4 * W'.a₂ * W'.a₄ * P y ^ 2 * P z ^ 2 - 27 * W'.a₂ * W'.a₆ * P x ^ 2 * P z ^ 2 + - 9 * W'.a₃ ^ 2 * P x ^ 3 * P z + 6 * W'.a₃ ^ 2 * P y ^ 2 * P z ^ 2 + - 12 * W'.a₃ * W'.a₄ * P x * P y * P z ^ 2 + 9 * W'.a₄ ^ 2 * P x ^ 2 * P z ^ 2 + - 2 * W'.a₁ ^ 3 * P x ^ 3 * P y + W'.a₁ ^ 3 * P y ^ 3 * P z + 3 * W'.a₁ ^ 2 * W'.a₂ * P x ^ 4 + + 2 * W'.a₁ ^ 2 * W'.a₂ * P x * P y ^ 2 * P z + 3 * W'.a₁ ^ 2 * W'.a₃ * P x ^ 2 * P y * P z + + 3 * W'.a₁ ^ 2 * W'.a₄ * P x ^ 3 * P z - W'.a₁ ^ 2 * W'.a₄ * P y ^ 2 * P z ^ 2 + - 12 * W'.a₁ * W'.a₂ ^ 2 * P x ^ 2 * P y * P z - 6 * W'.a₁ * W'.a₂ * W'.a₃ * P x ^ 3 * P z + + 4 * W'.a₁ * W'.a₂ * W'.a₃ * P y ^ 2 * P z ^ 2 + - 8 * W'.a₁ * W'.a₂ * W'.a₄ * P x * P y * P z ^ 2 + 6 * W'.a₁ * W'.a₃ ^ 2 * P x * P y * P z ^ 2 + - W'.a₁ * W'.a₄ ^ 2 * P y * P z ^ 3 + 8 * W'.a₂ ^ 3 * P x ^ 3 * P z + - 8 * W'.a₂ ^ 2 * W'.a₃ * P x * P y * P z ^ 2 + 12 * W'.a₂ ^ 2 * W'.a₄ * P x ^ 2 * P z ^ 2 + - 9 * W'.a₂ * W'.a₃ ^ 2 * P x ^ 2 * P z ^ 2 - 4 * W'.a₂ * W'.a₃ * W'.a₄ * P y * P z ^ 3 + + 6 * W'.a₂ * W'.a₄ ^ 2 * P x * P z ^ 3 + W'.a₃ ^ 3 * P y * P z ^ 3 + - 3 * W'.a₃ ^ 2 * W'.a₄ * P x * P z ^ 3 + W'.a₄ ^ 3 * P z ^ 4 + W'.a₁ ^ 4 * P x * P y ^ 2 * P z + - 3 * W'.a₁ ^ 3 * W'.a₂ * P x ^ 2 * P y * P z + W'.a₁ ^ 3 * W'.a₃ * P y ^ 2 * P z ^ 2 + - 2 * W'.a₁ ^ 3 * W'.a₄ * P x * P y * P z ^ 2 + 2 * W'.a₁ ^ 2 * W'.a₂ ^ 2 * P x ^ 3 * P z + - 2 * W'.a₁ ^ 2 * W'.a₂ * W'.a₃ * P x * P y * P z ^ 2 + + 3 * W'.a₁ ^ 2 * W'.a₂ * W'.a₄ * P x ^ 2 * P z ^ 2 + - 2 * W'.a₁ ^ 2 * W'.a₃ * W'.a₄ * P y * P z ^ 3 + W'.a₁ ^ 2 * W'.a₄ ^ 2 * P x * P z ^ 3 + + W'.a₁ * W'.a₂ * W'.a₃ ^ 2 * P y * P z ^ 3 + 2 * W'.a₁ * W'.a₂ * W'.a₃ * W'.a₄ * P x * P z ^ 3 + + W'.a₁ * W'.a₃ * W'.a₄ ^ 2 * P z ^ 4 - 2 * W'.a₂ ^ 2 * W'.a₃ ^ 2 * P x * P z ^ 3 + - W'.a₂ * W'.a₃ ^ 2 * W'.a₄ * P z ^ 4 + +lemma negDblY_eq' {P : Fin 3 → R} (hP : W'.Equation P) : W'.negDblY P * P z ^ 2 = + -eval P W'.polynomialX * (eval P W'.polynomialX ^ 2 + - W'.a₁ * eval P W'.polynomialX * P z * (P y - W'.negY P) + - W'.a₂ * P z ^ 2 * (P y - W'.negY P) ^ 2 - 2 * P x * P z * (P y - W'.negY P) ^ 2 + - P x * P z * (P y - W'.negY P) ^ 2) + P y * P z ^ 2 * (P y - W'.negY P) ^ 3 := by + linear_combination (norm := (rw [negDblY, eval_polynomialX, negY]; ring1)) + -9 * (P y ^ 2 * P z + 2 * W'.a₁ * P x * P y * P z - 3 * P x ^ 3 - 3 * W'.a₂ * P x ^ 2 * P z) + * (equation_iff _).mp hP + +lemma negDblY_eq {P : Fin 3 → F} (hP : W.Equation P) (hPz : P z ≠ 0) : W.negDblY P = + (-eval P W.polynomialX * (eval P W.polynomialX ^ 2 + - W.a₁ * eval P W.polynomialX * P z * (P y - W.negY P) + - W.a₂ * P z ^ 2 * (P y - W.negY P) ^ 2 - 2 * P x * P z * (P y - W.negY P) ^ 2 + - P x * P z * (P y - W.negY P) ^ 2) + P y * P z ^ 2 * (P y - W.negY P) ^ 3) / P z ^ 2 := by + rw [← negDblY_eq' hP, mul_div_cancel_right₀ _ <| pow_ne_zero 2 hPz] + +lemma negDblY_smul (P : Fin 3 → R) (u : R) : W'.negDblY (u • P) = u ^ 4 * W'.negDblY P := by + simp only [negDblY, smul_fin3_ext] + ring1 + +lemma negDblY_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Equation P) (hPz : P z = 0) : + W'.negDblY P = -P y ^ 4 := by + rw [negDblY, hPz, X_eq_zero_of_Z_eq_zero hP hPz] + ring1 + +lemma negDblY_of_Y_eq' [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W'.negY Q * P z) : + W'.negDblY P * P z ^ 2 = -eval P W'.polynomialX ^ 3 := by + rw [negDblY_eq' hP, Y_eq_negY_of_Y_eq hQz hx hy hy'] + ring1 + +lemma negDblY_of_Y_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W.negY Q * P z) : + W.negDblY P = -W.dblU P := by + rw [dblU, ← neg_div, ← negDblY_of_Y_eq' hP hQz hx hy hy', + mul_div_cancel_right₀ _ <| pow_ne_zero 2 hPz] + +private lemma toAffine_negAddY_of_eq {P : Fin 3 → F} (hPz : P z ≠ 0) {n d : F} (hd : d ≠ 0) : + W.toAffine.negAddY (P x / P z) (P x / P z) (P y / P z) (-n / P z / d) = + (-n * (n ^ 2 - W.a₁ * n * P z * d - W.a₂ * P z ^ 2 * d ^ 2 - 2 * P x * P z * d ^ 2 + - P x * P z * d ^ 2) + P y * P z ^ 2 * d ^ 3) / P z ^ 2 / (P z * d ^ 3) := by + rw [Affine.negAddY, toAffine_addX_of_eq hPz hd] + field_simp [mul_ne_zero hPz <| mul_ne_zero hPz <| pow_ne_zero 3 hd] + ring1 + +lemma negDblY_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ W.negY Q * P z) : + W.negDblY P / W.dblZ P = W.toAffine.negAddY (P x / P z) (Q x / Q z) (P y / P z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)) := by + rw [negDblY_eq hP hPz, dblZ, toAffine_slope_of_eq hP hQ hPz hQz hx hy, ← (X_eq_iff hPz hQz).mp hx, + toAffine_negAddY_of_eq hPz <| sub_ne_zero.mpr <| Y_ne_negY_of_Y_ne' hP hQ hPz hQz hx hy] + +variable (W') in +/-- The $Y$-coordinate of a representative of `2 • P` for a point `P`. -/ +noncomputable def dblY (P : Fin 3 → R) : R := + W'.negY ![W'.dblX P, W'.negDblY P, W'.dblZ P] + +lemma dblY_smul (P : Fin 3 → R) (u : R) : W'.dblY (u • P) = u ^ 4 * W'.dblY P := by + simp only [dblY, negY_eq, negDblY_smul, dblX_smul, dblZ_smul] + ring1 + +lemma dblY_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Equation P) (hPz : P z = 0) : + W'.dblY P = P y ^ 4 := by + rw [dblY, negY_eq, negDblY_of_Z_eq_zero hP hPz, dblX_of_Z_eq_zero hP hPz, dblZ_of_Z_eq_zero hPz] + ring1 + +lemma dblY_of_Y_eq' [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) + (hy' : P y * Q z = W'.negY Q * P z) : W'.dblY P * P z ^ 2 = eval P W'.polynomialX ^ 3 := by + linear_combination (norm := (rw [dblY, negY_eq, dblX_of_Y_eq hP hPz hQz hx hy hy', + dblZ_of_Y_eq hQz hx hy hy']; ring1)) -negDblY_of_Y_eq' hP hQz hx hy hy' + +lemma dblY_of_Y_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W.negY Q * P z) : + W.dblY P = W.dblU P := by + rw [dblU, ← dblY_of_Y_eq' hP hPz hQz hx hy hy', mul_div_cancel_right₀ _ <| pow_ne_zero 2 hPz] + +lemma dblY_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ W.negY Q * P z) : + W.dblY P / W.dblZ P = W.toAffine.addY (P x / P z) (Q x / Q z) (P y / P z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)) := by + erw [dblY, negY_of_Z_ne_zero <| dblZ_ne_zero_of_Y_ne' hP hQ hPz hQz hx hy, + dblX_of_Z_ne_zero hP hQ hPz hQz hx hy, negDblY_of_Z_ne_zero hP hQ hPz hQz hx hy, Affine.addY] + +variable (W') in +/-- The coordinates of a representative of `2 • P` for a point `P`. -/ +noncomputable def dblXYZ (P : Fin 3 → R) : Fin 3 → R := + ![W'.dblX P, W'.dblY P, W'.dblZ P] + +lemma dblXYZ_X (P : Fin 3 → R) : W'.dblXYZ P x = W'.dblX P := + rfl + +lemma dblXYZ_Y (P : Fin 3 → R) : W'.dblXYZ P y = W'.dblY P := + rfl + +lemma dblXYZ_Z (P : Fin 3 → R) : W'.dblXYZ P z = W'.dblZ P := + rfl + +lemma dblXYZ_smul (P : Fin 3 → R) (u : R) : W'.dblXYZ (u • P) = u ^ 4 • W'.dblXYZ P := by + rw [dblXYZ, dblX_smul, dblY_smul, dblZ_smul, smul_fin3, dblXYZ_X, dblXYZ_Y, dblXYZ_Z] + +lemma dblXYZ_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Equation P) (hPz : P z = 0) : + W'.dblXYZ P = P y ^ 4 • ![0, 1, 0] := by + erw [dblXYZ, dblX_of_Z_eq_zero hP hPz, dblY_of_Z_eq_zero hP hPz, dblZ_of_Z_eq_zero hPz, smul_fin3, + mul_zero, mul_one] + +lemma dblXYZ_of_Y_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) (hy' : P y * Q z = W.negY Q * P z) : + W.dblXYZ P = W.dblU P • ![0, 1, 0] := by + erw [dblXYZ, dblX_of_Y_eq hP hPz hQz hx hy hy', dblY_of_Y_eq hP hPz hQz hx hy hy', + dblZ_of_Y_eq hQz hx hy hy', smul_fin3, mul_zero, mul_one] + +lemma dblXYZ_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) (hy : P y * Q z ≠ W.negY Q * P z) : + W.dblXYZ P = W.dblZ P • + ![W.toAffine.addX (P x / P z) (Q x / Q z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)), + W.toAffine.addY (P x / P z) (Q x / Q z) (P y / P z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)), 1] := by + have hZ : IsUnit <| W.dblZ P := isUnit_dblZ_of_Y_ne' hP hQ hPz hQz hx hy + erw [dblXYZ, smul_fin3, ← dblX_of_Z_ne_zero hP hQ hPz hQz hx hy, hZ.mul_div_cancel, + ← dblY_of_Z_ne_zero hP hQ hPz hQz hx hy, hZ.mul_div_cancel, mul_one] + +end Doubling + +section Addition + +/-! ### Addition formulae -/ + +/-- The unit associated to the addition of a non-2-torsion point `P` with its negation. +More specifically, the unit `u` such that `W.add P Q = u • ![0, 1, 0]` where `P x / P z = Q x / Q z` +but `P ≠ W.neg P`. -/ +def addU (P Q : Fin 3 → F) : F := + -(P y * Q z - Q y * P z) ^ 3 / (P z * Q z) + +lemma addU_smul {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) {u v : F} (hu : u ≠ 0) + (hv : v ≠ 0) : addU (u • P) (v • Q) = (u * v) ^ 2 * addU P Q := by + field_simp [addU, smul_fin3_ext] + ring1 + +lemma addU_of_Z_eq_zero_left {P Q : Fin 3 → F} (hPz : P z = 0) : addU P Q = 0 := by + rw [addU, hPz, zero_mul, div_zero] + +lemma addU_of_Z_eq_zero_right {P Q : Fin 3 → F} (hQz : Q z = 0) : addU P Q = 0 := by + rw [addU, hQz, mul_zero <| P z, div_zero] + +lemma addU_ne_zero_of_Y_ne {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hy : P y * Q z ≠ Q y * P z) : addU P Q ≠ 0 := + div_ne_zero (neg_ne_zero.mpr <| pow_ne_zero 3 <| sub_ne_zero.mpr hy) <| mul_ne_zero hPz hQz + +lemma isUnit_addU_of_Y_ne {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hy : P y * Q z ≠ Q y * P z) : IsUnit (addU P Q) := + (addU_ne_zero_of_Y_ne hPz hQz hy).isUnit + +variable (W') in +/-- The $Z$-coordinate of a representative of `P + Q` for two distinct points `P` and `Q`. +Note that this returns the value 0 if the representatives of `P` and `Q` are equal. -/ +def addZ (P Q : Fin 3 → R) : R := + -3 * P x ^ 2 * Q x * Q z + 3 * P x * Q x ^ 2 * P z + P y ^ 2 * Q z ^ 2 - Q y ^ 2 * P z ^ 2 + + W'.a₁ * P x * P y * Q z ^ 2 - W'.a₁ * Q x * Q y * P z ^ 2 - W'.a₂ * P x ^ 2 * Q z ^ 2 + + W'.a₂ * Q x ^ 2 * P z ^ 2 + W'.a₃ * P y * P z * Q z ^ 2 - W'.a₃ * Q y * P z ^ 2 * Q z + - W'.a₄ * P x * P z * Q z ^ 2 + W'.a₄ * Q x * P z ^ 2 * Q z + +lemma addZ_eq' {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) : + W'.addZ P Q * (P z * Q z) = (P x * Q z - Q x * P z) ^ 3 := by + linear_combination (norm := (rw [addZ]; ring1)) + Q z ^ 3 * (equation_iff _).mp hP - P z ^ 3 * (equation_iff _).mp hQ + +lemma addZ_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) : W.addZ P Q = (P x * Q z - Q x * P z) ^ 3 / (P z * Q z) := by + rw [← addZ_eq' hP hQ, mul_div_cancel_right₀ _ <| mul_ne_zero hPz hQz] + +lemma addZ_smul (P Q : Fin 3 → R) (u v : R) : + W'.addZ (u • P) (v • Q) = (u * v) ^ 2 * W'.addZ P Q := by + simp only [addZ, smul_fin3_ext] + ring1 + +lemma addZ_self (P : Fin 3 → R) : W'.addZ P P = 0 := by + rw [addZ] + ring1 + +lemma addZ_of_Z_eq_zero_left [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hPz : P z = 0) : W'.addZ P Q = P y ^ 2 * Q z * Q z := by + rw [addZ, hPz, X_eq_zero_of_Z_eq_zero hP hPz] + ring1 + +lemma addZ_of_Z_eq_zero_right [NoZeroDivisors R] {P Q : Fin 3 → R} (hQ : W'.Equation Q) + (hQz : Q z = 0) : W'.addZ P Q = -(Q y ^ 2 * P z) * P z := by + rw [addZ, hQz, X_eq_zero_of_Z_eq_zero hQ hQz] + ring1 + +lemma addZ_of_X_eq [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) : W'.addZ P Q = 0 := by + apply eq_zero_of_ne_zero_of_mul_right_eq_zero <| mul_ne_zero hPz hQz + rw [addZ_eq' hP hQ, hx, sub_self, zero_pow three_ne_zero] + +lemma addZ_ne_zero_of_X_ne [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hQ : W'.Equation Q) (hx : P x * Q z ≠ Q x * P z) : W'.addZ P Q ≠ 0 := + addZ_eq' hP hQ ▸ left_ne_zero_of_mul <| pow_ne_zero 3 <| sub_ne_zero.mpr hx + +lemma isUnit_addZ_of_X_ne {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) + (hx : P x * Q z ≠ Q x * P z) : IsUnit <| W.addZ P Q := + (addZ_ne_zero_of_X_ne hP hQ hx).isUnit + +private lemma toAffine_slope_of_ne {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z ≠ Q x * P z) : + W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z) = + (P y * Q z - Q y * P z) / (P x * Q z - Q x * P z) := by + field_simp [Affine.slope_of_X_ne <| by rwa [ne_eq, ← X_eq_iff hPz hQz]] + ring1 + +variable (W') in +/-- The $X$-coordinate of a representative of `P + Q` for two distinct points `P` and `Q`. +Note that this returns the value 0 if the representatives of `P` and `Q` are equal. -/ +def addX (P Q : Fin 3 → R) : R := + -P x * Q y ^ 2 * P z + Q x * P y ^ 2 * Q z - 2 * P x * P y * Q y * Q z + 2 * Q x * P y * Q y * P z + - W'.a₁ * P x ^ 2 * Q y * Q z + W'.a₁ * Q x ^ 2 * P y * P z + W'.a₂ * P x ^ 2 * Q x * Q z + - W'.a₂ * P x * Q x ^ 2 * P z - W'.a₃ * P x * P y * Q z ^ 2 + W'.a₃ * Q x * Q y * P z ^ 2 + - 2 * W'.a₃ * P x * Q y * P z * Q z + 2 * W'.a₃ * Q x * P y * P z * Q z + + W'.a₄ * P x ^ 2 * Q z ^ 2 - W'.a₄ * Q x ^ 2 * P z ^ 2 + 3 * W'.a₆ * P x * P z * Q z ^ 2 + - 3 * W'.a₆ * Q x * P z ^ 2 * Q z + +lemma addX_eq' {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) : + W'.addX P Q * (P z * Q z) ^ 2 = + ((P y * Q z - Q y * P z) ^ 2 * P z * Q z + + W'.a₁ * (P y * Q z - Q y * P z) * P z * Q z * (P x * Q z - Q x * P z) + - W'.a₂ * P z * Q z * (P x * Q z - Q x * P z) ^ 2 - P x * Q z * (P x * Q z - Q x * P z) ^ 2 + - Q x * P z * (P x * Q z - Q x * P z) ^ 2) * (P x * Q z - Q x * P z) := by + linear_combination (norm := (rw [addX]; ring1)) + (2 * Q x * P z * Q z ^ 3 - P x * Q z ^ 4) * (equation_iff _).mp hP + + (Q x * P z ^ 4 - 2 * P x * P z ^ 3 * Q z) * (equation_iff _).mp hQ + +lemma addX_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) : W.addX P Q = + ((P y * Q z - Q y * P z) ^ 2 * P z * Q z + + W.a₁ * (P y * Q z - Q y * P z) * P z * Q z * (P x * Q z - Q x * P z) + - W.a₂ * P z * Q z * (P x * Q z - Q x * P z) ^ 2 - P x * Q z * (P x * Q z - Q x * P z) ^ 2 + - Q x * P z * (P x * Q z - Q x * P z) ^ 2) * (P x * Q z - Q x * P z) / (P z * Q z) ^ 2 := by + rw [← addX_eq' hP hQ, mul_div_cancel_right₀ _ <| pow_ne_zero 2 <| mul_ne_zero hPz hQz] + +lemma addX_smul (P Q : Fin 3 → R) (u v : R) : + W'.addX (u • P) (v • Q) = (u * v) ^ 2 * W'.addX P Q := by + simp only [addX, smul_fin3_ext] + ring1 + +lemma addX_self (P : Fin 3 → R) : W'.addX P P = 0 := by + rw [addX] + ring1 + +lemma addX_of_Z_eq_zero_left [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hPz : P z = 0) : W'.addX P Q = P y ^ 2 * Q z * Q x := by + rw [addX, hPz, X_eq_zero_of_Z_eq_zero hP hPz] + ring1 + +lemma addX_of_Z_eq_zero_right [NoZeroDivisors R] {P Q : Fin 3 → R} (hQ : W'.Equation Q) + (hQz : Q z = 0) : W'.addX P Q = -(Q y ^ 2 * P z) * P x := by + rw [addX, hQz, X_eq_zero_of_Z_eq_zero hQ hQz] + ring1 + +lemma addX_of_X_eq [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) : W'.addX P Q = 0 := by + apply eq_zero_of_ne_zero_of_mul_right_eq_zero <| pow_ne_zero 2 <| mul_ne_zero hPz hQz + rw [addX_eq' hP hQ, hx] + ring1 + +private lemma toAffine_addX_of_ne {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) {n d : F} + (hd : d ≠ 0) : W.toAffine.addX (P x / P z) (Q x / Q z) (n / d) = + (n ^ 2 * P z * Q z + W.a₁ * n * P z * Q z * d - W.a₂ * P z * Q z * d ^ 2 - P x * Q z * d ^ 2 + - Q x * P z * d ^ 2) * d / (P z * Q z) ^ 2 / (d ^ 3 / (P z * Q z)) := by + field_simp [hd] + ring1 + +lemma addX_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z ≠ Q x * P z) : W.addX P Q / W.addZ P Q = + W.toAffine.addX (P x / P z) (Q x / Q z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)) := by + rw [addX_eq hP hQ hPz hQz, addZ_eq hP hQ hPz hQz, toAffine_slope_of_ne hPz hQz hx, + toAffine_addX_of_ne hPz hQz <| sub_ne_zero.mpr hx] + +variable (W') in +/-- The $Y$-coordinate of a representative of `-(P + Q)` for two distinct points `P` and `Q`. +Note that this returns the value 0 if the representatives of `P` and `Q` are equal. -/ +def negAddY (P Q : Fin 3 → R) : R := + -3 * P x ^ 2 * Q x * Q y + 3 * P x * Q x ^ 2 * P y - P y ^ 2 * Q y * Q z + P y * Q y ^ 2 * P z + + W'.a₁ * P x * Q y ^ 2 * P z - W'.a₁ * Q x * P y ^ 2 * Q z - W'.a₂ * P x ^ 2 * Q y * Q z + + W'.a₂ * Q x ^ 2 * P y * P z + 2 * W'.a₂ * P x * Q x * P y * Q z + - 2 * W'.a₂ * P x * Q x * Q y * P z - W'.a₃ * P y ^ 2 * Q z ^ 2 + W'.a₃ * Q y ^ 2 * P z ^ 2 + + W'.a₄ * P x * P y * Q z ^ 2 - 2 * W'.a₄ * P x * Q y * P z * Q z + + 2 * W'.a₄ * Q x * P y * P z * Q z - W'.a₄ * Q x * Q y * P z ^ 2 + + 3 * W'.a₆ * P y * P z * Q z ^ 2 - 3 * W'.a₆ * Q y * P z ^ 2 * Q z + +lemma negAddY_eq' {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) : + W'.negAddY P Q * (P z * Q z) ^ 2 = + (P y * Q z - Q y * P z) * ((P y * Q z - Q y * P z) ^ 2 * P z * Q z + + W'.a₁ * (P y * Q z - Q y * P z) * P z * Q z * (P x * Q z - Q x * P z) + - W'.a₂ * P z * Q z * (P x * Q z - Q x * P z) ^ 2 - P x * Q z * (P x * Q z - Q x * P z) ^ 2 + - Q x * P z * (P x * Q z - Q x * P z) ^ 2 - P x * Q z * (P x * Q z - Q x * P z) ^ 2) + + P y * Q z * (P x * Q z - Q x * P z) ^ 3 := by + linear_combination (norm := (rw [negAddY]; ring1)) + (2 * Q y * P z * Q z ^ 3 - P y * Q z ^ 4) * (equation_iff _).mp hP + + (Q y * P z ^ 4 - 2 * P y * P z ^ 3 * Q z) * (equation_iff _).mp hQ + +lemma negAddY_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) : W.negAddY P Q = + ((P y * Q z - Q y * P z) * ((P y * Q z - Q y * P z) ^ 2 * P z * Q z + + W.a₁ * (P y * Q z - Q y * P z) * P z * Q z * (P x * Q z - Q x * P z) + - W.a₂ * P z * Q z * (P x * Q z - Q x * P z) ^ 2 - P x * Q z * (P x * Q z - Q x * P z) ^ 2 + - Q x * P z * (P x * Q z - Q x * P z) ^ 2 - P x * Q z * (P x * Q z - Q x * P z) ^ 2) + + P y * Q z * (P x * Q z - Q x * P z) ^ 3) / (P z * Q z) ^ 2 := by + rw [← negAddY_eq' hP hQ, mul_div_cancel_right₀ _ <| pow_ne_zero 2 <| mul_ne_zero hPz hQz] + +lemma negAddY_smul (P Q : Fin 3 → R) (u v : R) : + W'.negAddY (u • P) (v • Q) = (u * v) ^ 2 * W'.negAddY P Q := by + simp only [negAddY, smul_fin3_ext] + ring1 + +lemma negAddY_self (P : Fin 3 → R) : W'.negAddY P P = 0 := by + rw [negAddY] + ring1 + +lemma negAddY_of_Z_eq_zero_left [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hPz : P z = 0) : W'.negAddY P Q = P y ^ 2 * Q z * W'.negY Q := by + rw [negAddY, hPz, X_eq_zero_of_Z_eq_zero hP hPz, negY] + ring1 + +lemma negAddY_of_Z_eq_zero_right [NoZeroDivisors R] {P Q : Fin 3 → R} (hQ : W'.Equation Q) + (hQz : Q z = 0) : W'.negAddY P Q = -(Q y ^ 2 * P z) * W'.negY P := by + rw [negAddY, hQz, X_eq_zero_of_Z_eq_zero hQ hQz, negY] + ring1 + +lemma negAddY_of_X_eq' {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hx : P x * Q z = Q x * P z) : + W'.negAddY P Q * (P z * Q z) ^ 2 = (P y * Q z - Q y * P z) ^ 3 * (P z * Q z) := by + rw [negAddY_eq' hP hQ, hx] + ring1 + +lemma negAddY_of_X_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) : W.negAddY P Q = -addU P Q := by + rw [addU, neg_div, neg_neg, ← mul_div_mul_right _ _ <| mul_ne_zero hPz hQz, + ← negAddY_of_X_eq' hP hQ hx, ← sq, + mul_div_cancel_right₀ _ <| pow_ne_zero 2 <| mul_ne_zero hPz hQz] + +private lemma toAffine_negAddY_of_ne {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) {n d : F} + (hd : d ≠ 0) : W.toAffine.negAddY (P x / P z) (Q x / Q z) (P y / P z) (n / d) = + (n * (n ^ 2 * P z * Q z + W.a₁ * n * P z * Q z * d - W.a₂ * P z * Q z * d ^ 2 + - P x * Q z * d ^ 2 - Q x * P z * d ^ 2 - P x * Q z * d ^ 2) + P y * Q z * d ^ 3) + / (P z * Q z) ^ 2 / (d ^ 3 / (P z * Q z)) := by + rw [Affine.negAddY, toAffine_addX_of_ne hPz hQz hd] + field_simp [mul_ne_zero (pow_ne_zero 2 <| mul_ne_zero hPz hQz) <| pow_ne_zero 3 hd] + ring1 + +lemma negAddY_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z ≠ Q x * P z) : W.negAddY P Q / W.addZ P Q = + W.toAffine.negAddY (P x / P z) (Q x / Q z) (P y / P z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)) := by + rw [negAddY_eq hP hQ hPz hQz, addZ_eq hP hQ hPz hQz, toAffine_slope_of_ne hPz hQz hx, + toAffine_negAddY_of_ne hPz hQz <| sub_ne_zero.mpr hx] + +variable (W') in +/-- The $Y$-coordinate of a representative of `P + Q` for two distinct points `P` and `Q`. +Note that this returns the value 0 if the representatives of `P` and `Q` are equal. -/ +def addY (P Q : Fin 3 → R) : R := + W'.negY ![W'.addX P Q, W'.negAddY P Q, W'.addZ P Q] + +lemma addY_smul (P Q : Fin 3 → R) (u v : R) : + W'.addY (u • P) (v • Q) = (u * v) ^ 2 * W'.addY P Q := by + simp only [addY, negY_eq, negAddY_smul, addX_smul, addZ_smul] + ring1 + +lemma addY_self (P : Fin 3 → R) : W'.addY P P = 0 := by + simp only [addY, negY_eq, negAddY_self, addX_self, addZ_self, neg_zero, mul_zero, sub_zero] + +lemma addY_of_Z_eq_zero_left [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hPz : P z = 0) : W'.addY P Q = P y ^ 2 * Q z * Q y := by + rw [addY, negY_eq, negAddY_of_Z_eq_zero_left hP hPz, negY, addX_of_Z_eq_zero_left hP hPz, + addZ_of_Z_eq_zero_left hP hPz] + ring1 + +lemma addY_of_Z_eq_zero_right [NoZeroDivisors R] {P Q : Fin 3 → R} (hQ : W'.Equation Q) + (hQz : Q z = 0) : W'.addY P Q = -(Q y ^ 2 * P z) * P y := by + rw [addY, negY_eq, negAddY_of_Z_eq_zero_right hQ hQz, negY, addX_of_Z_eq_zero_right hQ hQz, + addZ_of_Z_eq_zero_right hQ hQz] + ring1 + +lemma addY_of_X_eq' [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) (hQ : W'.Equation Q) + (hPz : P z ≠ 0) (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) : + W'.addY P Q * (P z * Q z) ^ 3 = -(P y * Q z - Q y * P z) ^ 3 * (P z * Q z) ^ 2 := by + linear_combination (norm := (rw [addY, negY_eq, addX_of_X_eq hP hQ hPz hQz hx, + addZ_of_X_eq hP hQ hPz hQz hx]; ring1)) -(P z * Q z) * negAddY_of_X_eq' hP hQ hx + +lemma addY_of_X_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) : W.addY P Q = addU P Q := by + rw [addU, ← mul_div_mul_right _ _ <| pow_ne_zero 2 <| mul_ne_zero hPz hQz, + ← addY_of_X_eq' hP hQ hPz hQz hx, ← pow_succ', + mul_div_cancel_right₀ _ <| pow_ne_zero 3 <| mul_ne_zero hPz hQz] + +lemma addY_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z ≠ Q x * P z) : W.addY P Q / W.addZ P Q = + W.toAffine.addY (P x / P z) (Q x / Q z) (P y / P z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)) := by + erw [addY, negY_of_Z_ne_zero <| addZ_ne_zero_of_X_ne hP hQ hx, addX_of_Z_ne_zero hP hQ hPz hQz hx, + negAddY_of_Z_ne_zero hP hQ hPz hQz hx, Affine.addY] + +variable (W') in +/-- The coordinates of a representative of `P + Q` for two distinct points `P` and `Q`. +Note that this returns the value `![0, 0, 0]` if the representatives of `P` and `Q` are equal. -/ +noncomputable def addXYZ (P Q : Fin 3 → R) : Fin 3 → R := + ![W'.addX P Q, W'.addY P Q, W'.addZ P Q] + +lemma addXYZ_X (P Q : Fin 3 → R) : W'.addXYZ P Q x = W'.addX P Q := + rfl + +lemma addXYZ_Y (P Q : Fin 3 → R) : W'.addXYZ P Q y = W'.addY P Q := + rfl + +lemma addXYZ_Z (P Q : Fin 3 → R) : W'.addXYZ P Q z = W'.addZ P Q := + rfl + +lemma addXYZ_smul (P Q : Fin 3 → R) (u v : R) : + W'.addXYZ (u • P) (v • Q) = (u * v) ^ 2 • W'.addXYZ P Q := by + rw [addXYZ, addX_smul, addY_smul, addZ_smul, smul_fin3, addXYZ_X, addXYZ_Y, addXYZ_Z] + +lemma addXYZ_self (P : Fin 3 → R) : W'.addXYZ P P = ![0, 0, 0] := by + rw [addXYZ, addX_self, addY_self, addZ_self] + +lemma addXYZ_of_Z_eq_zero_left [NoZeroDivisors R] {P Q : Fin 3 → R} (hP : W'.Equation P) + (hPz : P z = 0) : W'.addXYZ P Q = (P y ^ 2 * Q z) • Q := by + rw [addXYZ, addX_of_Z_eq_zero_left hP hPz, addY_of_Z_eq_zero_left hP hPz, + addZ_of_Z_eq_zero_left hP hPz, smul_fin3] + +lemma addXYZ_of_Z_eq_zero_right [NoZeroDivisors R] {P Q : Fin 3 → R} (hQ : W'.Equation Q) + (hQz : Q z = 0) : W'.addXYZ P Q = -(Q y ^ 2 * P z) • P := by + rw [addXYZ, addX_of_Z_eq_zero_right hQ hQz, addY_of_Z_eq_zero_right hQ hQz, + addZ_of_Z_eq_zero_right hQ hQz, smul_fin3] + +lemma addXYZ_of_X_eq {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z = Q x * P z) : W.addXYZ P Q = addU P Q • ![0, 1, 0] := by + erw [addXYZ, addX_of_X_eq hP hQ hPz hQz hx, addY_of_X_eq hP hQ hPz hQz hx, + addZ_of_X_eq hP hQ hPz hQz hx, smul_fin3, mul_zero, mul_one] + +lemma addXYZ_of_Z_ne_zero {P Q : Fin 3 → F} (hP : W.Equation P) (hQ : W.Equation Q) (hPz : P z ≠ 0) + (hQz : Q z ≠ 0) (hx : P x * Q z ≠ Q x * P z) : W.addXYZ P Q = W.addZ P Q • + ![W.toAffine.addX (P x / P z) (Q x / Q z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)), + W.toAffine.addY (P x / P z) (Q x / Q z) (P y / P z) + (W.toAffine.slope (P x / P z) (Q x / Q z) (P y / P z) (Q y / Q z)), 1] := by + have hZ : IsUnit <| W.addZ P Q := isUnit_addZ_of_X_ne hP hQ hx + erw [addXYZ, smul_fin3, ← addX_of_Z_ne_zero hP hQ hPz hQz hx, hZ.mul_div_cancel, + ← addY_of_Z_ne_zero hP hQ hPz hQz hx, hZ.mul_div_cancel, mul_one] + +end Addition + end WeierstrassCurve.Projective From 554374891a7982b9da2ff76b51a8ebf0ae6caceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Thu, 19 Sep 2024 18:27:53 +0000 Subject: [PATCH 054/170] chore(Probability/Kernel): split Kernel.Basic (#16931) Kernel.Basic becomes 3 files: - Kernel.Defs with definitions of kernels and classes of kernels - Kernel.Basic with definitions of basic kernels (deterministic, const...) - Kernel.Integral with lemmas about Bochner integrals against those basic kernels I also created a new file Independence.Integrable because the split revealed that Independence.Basic depended on the definition of Lp spaces and integrability only through two lemmas. I added one lemma, `integral_restrict` (in Kernel.Integral), because all kernels had lemmas about integral and setIntegral except that one for which the integral lemma was missing. --- Mathlib.lean | 3 + Mathlib/Probability/Independence/Basic.lean | 43 +- .../Probability/Independence/Integrable.lean | 54 +++ Mathlib/Probability/Independence/Kernel.lean | 1 + Mathlib/Probability/Kernel/Basic.lean | 432 +----------------- Mathlib/Probability/Kernel/Defs.lean | 354 ++++++++++++++ Mathlib/Probability/Kernel/Integral.lean | 130 ++++++ .../Kernel/MeasurableIntegral.lean | 3 +- Mathlib/Probability/StrongLaw.lean | 1 + 9 files changed, 558 insertions(+), 463 deletions(-) create mode 100644 Mathlib/Probability/Independence/Integrable.lean create mode 100644 Mathlib/Probability/Kernel/Defs.lean create mode 100644 Mathlib/Probability/Kernel/Integral.lean diff --git a/Mathlib.lean b/Mathlib.lean index 6be5ea0a0fee1..25ed629a1b106 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3733,6 +3733,7 @@ import Mathlib.Probability.Distributions.Uniform import Mathlib.Probability.IdentDistrib import Mathlib.Probability.Independence.Basic import Mathlib.Probability.Independence.Conditional +import Mathlib.Probability.Independence.Integrable import Mathlib.Probability.Independence.Kernel import Mathlib.Probability.Independence.ZeroOne import Mathlib.Probability.Integration @@ -3740,6 +3741,7 @@ import Mathlib.Probability.Kernel.Basic import Mathlib.Probability.Kernel.Composition import Mathlib.Probability.Kernel.CondDistrib import Mathlib.Probability.Kernel.Condexp +import Mathlib.Probability.Kernel.Defs import Mathlib.Probability.Kernel.Disintegration.Basic import Mathlib.Probability.Kernel.Disintegration.CDFToKernel import Mathlib.Probability.Kernel.Disintegration.CondCDF @@ -3748,6 +3750,7 @@ import Mathlib.Probability.Kernel.Disintegration.Integral import Mathlib.Probability.Kernel.Disintegration.MeasurableStieltjes import Mathlib.Probability.Kernel.Disintegration.StandardBorel import Mathlib.Probability.Kernel.Disintegration.Unique +import Mathlib.Probability.Kernel.Integral import Mathlib.Probability.Kernel.IntegralCompProd import Mathlib.Probability.Kernel.Invariance import Mathlib.Probability.Kernel.MeasurableIntegral diff --git a/Mathlib/Probability/Independence/Basic.lean b/Mathlib/Probability/Independence/Basic.lean index cd225daccfa3e..cf6f2aebad8a9 100644 --- a/Mathlib/Probability/Independence/Basic.lean +++ b/Mathlib/Probability/Independence/Basic.lean @@ -64,6 +64,8 @@ when defining `μ` in the example above, the measurable space used is the last o Part A, Chapter 4. -/ +assert_not_exists MeasureTheory.Integrable + open MeasureTheory MeasurableSpace Set open scoped MeasureTheory ENNReal @@ -715,44 +717,3 @@ theorem iIndepSet.iIndepFun_indicator [Zero β] [One β] {m : MeasurableSpace β end IndepFun end ProbabilityTheory - -namespace MeasureTheory - -open Filter ProbabilityTheory -open scoped NNReal Topology - -/-- If a nonzero function belongs to `ℒ^p` and is independent of another function, then -the space is a probability space. -/ -lemma Memℒp.isProbabilityMeasure_of_indepFun - {Ω : Type*} [MeasurableSpace Ω] {μ : Measure Ω} - {E : Type*} [NormedAddCommGroup E] [MeasurableSpace E] [BorelSpace E] - {F : Type*} [MeasurableSpace F] - (f : Ω → E) (g : Ω → F) {p : ℝ≥0∞} (hp : p ≠ 0) (hp' : p ≠ ∞) - (hℒp : Memℒp f p μ) (h'f : ¬(∀ᵐ ω ∂μ, f ω = 0)) (hindep : IndepFun f g μ) : - IsProbabilityMeasure μ := by - obtain ⟨c, c_pos, hc⟩ : ∃ (c : ℝ≥0), 0 < c ∧ 0 < μ {ω | c ≤ ‖f ω‖₊} := by - contrapose! h'f - have A (c : ℝ≥0) (hc : 0 < c) : ∀ᵐ ω ∂μ, ‖f ω‖₊ < c := by simpa [ae_iff] using h'f c hc - obtain ⟨u, -, u_pos, u_lim⟩ : ∃ u, StrictAnti u ∧ (∀ (n : ℕ), 0 < u n) - ∧ Tendsto u atTop (𝓝 0) := exists_seq_strictAnti_tendsto (0 : ℝ≥0) - filter_upwards [ae_all_iff.2 (fun n ↦ A (u n) (u_pos n))] with ω hω - simpa using ge_of_tendsto' u_lim (fun i ↦ (hω i).le) - have h'c : μ {ω | c ≤ ‖f ω‖₊} < ∞ := hℒp.meas_ge_lt_top hp hp' c_pos.ne' - have := hindep.measure_inter_preimage_eq_mul {x | c ≤ ‖x‖₊} Set.univ - (isClosed_le continuous_const continuous_nnnorm).measurableSet MeasurableSet.univ - simp only [Set.preimage_setOf_eq, Set.preimage_univ, Set.inter_univ] at this - exact ⟨(ENNReal.mul_eq_left hc.ne' h'c.ne).1 this.symm⟩ - -/-- If a nonzero function is integrable and is independent of another function, then -the space is a probability space. -/ -lemma Integrable.isProbabilityMeasure_of_indepFun - {Ω : Type*} [MeasurableSpace Ω] {μ : Measure Ω} - {E : Type*} [NormedAddCommGroup E] [MeasurableSpace E] [BorelSpace E] - {F : Type*} [MeasurableSpace F] - (f : Ω → E) (g : Ω → F) - (hf : Integrable f μ) (h'f : ¬(∀ᵐ ω ∂μ, f ω = 0)) (hindep : IndepFun f g μ) : - IsProbabilityMeasure μ := - Memℒp.isProbabilityMeasure_of_indepFun f g one_ne_zero ENNReal.one_ne_top - (memℒp_one_iff_integrable.mpr hf) h'f hindep - -end MeasureTheory diff --git a/Mathlib/Probability/Independence/Integrable.lean b/Mathlib/Probability/Independence/Integrable.lean new file mode 100644 index 0000000000000..c33b372d816a2 --- /dev/null +++ b/Mathlib/Probability/Independence/Integrable.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2024 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel +-/ +import Mathlib.MeasureTheory.Function.L1Space +import Mathlib.Probability.Independence.Basic + +/-! +# Independence of functions implies that the measure is a probability measure + +If a nonzero function belongs to `ℒ^p` (in particular if it is integrable) and is independent +of another function, then the space is a probability space. + +-/ + +open Filter ProbabilityTheory + +open scoped ENNReal NNReal Topology + +namespace MeasureTheory + +variable {Ω E F: Type*} [MeasurableSpace Ω] {μ : Measure Ω} + [NormedAddCommGroup E] [MeasurableSpace E] [BorelSpace E] + [MeasurableSpace F] + +/-- If a nonzero function belongs to `ℒ^p` and is independent of another function, then +the space is a probability space. -/ +lemma Memℒp.isProbabilityMeasure_of_indepFun + (f : Ω → E) (g : Ω → F) {p : ℝ≥0∞} (hp : p ≠ 0) (hp' : p ≠ ∞) + (hℒp : Memℒp f p μ) (h'f : ¬ (∀ᵐ ω ∂μ, f ω = 0)) (hindep : IndepFun f g μ) : + IsProbabilityMeasure μ := by + obtain ⟨c, c_pos, hc⟩ : ∃ (c : ℝ≥0), 0 < c ∧ 0 < μ {ω | c ≤ ‖f ω‖₊} := by + contrapose! h'f + have A (c : ℝ≥0) (hc : 0 < c) : ∀ᵐ ω ∂μ, ‖f ω‖₊ < c := by simpa [ae_iff] using h'f c hc + obtain ⟨u, -, u_pos, u_lim⟩ : ∃ u, StrictAnti u ∧ (∀ (n : ℕ), 0 < u n) + ∧ Tendsto u atTop (𝓝 0) := exists_seq_strictAnti_tendsto (0 : ℝ≥0) + filter_upwards [ae_all_iff.2 (fun n ↦ A (u n) (u_pos n))] with ω hω + simpa using ge_of_tendsto' u_lim (fun i ↦ (hω i).le) + have h'c : μ {ω | c ≤ ‖f ω‖₊} < ∞ := hℒp.meas_ge_lt_top hp hp' c_pos.ne' + have := hindep.measure_inter_preimage_eq_mul {x | c ≤ ‖x‖₊} Set.univ + (isClosed_le continuous_const continuous_nnnorm).measurableSet MeasurableSet.univ + simp only [Set.preimage_setOf_eq, Set.preimage_univ, Set.inter_univ] at this + exact ⟨(ENNReal.mul_eq_left hc.ne' h'c.ne).1 this.symm⟩ + +/-- If a nonzero function is integrable and is independent of another function, then +the space is a probability space. -/ +lemma Integrable.isProbabilityMeasure_of_indepFun (f : Ω → E) (g : Ω → F) + (hf : Integrable f μ) (h'f : ¬ (∀ᵐ ω ∂μ, f ω = 0)) (hindep : IndepFun f g μ) : + IsProbabilityMeasure μ := + Memℒp.isProbabilityMeasure_of_indepFun f g one_ne_zero ENNReal.one_ne_top + (memℒp_one_iff_integrable.mpr hf) h'f hindep + +end MeasureTheory diff --git a/Mathlib/Probability/Independence/Kernel.lean b/Mathlib/Probability/Independence/Kernel.lean index ed4fbcb838ea5..146667d5bfbdb 100644 --- a/Mathlib/Probability/Independence/Kernel.lean +++ b/Mathlib/Probability/Independence/Kernel.lean @@ -5,6 +5,7 @@ Authors: Rémy Degenne -/ import Mathlib.MeasureTheory.Constructions.Pi import Mathlib.Probability.Kernel.Basic +import Mathlib.Tactic.Peel /-! # Independence with respect to a kernel and a measure diff --git a/Mathlib/Probability/Kernel/Basic.lean b/Mathlib/Probability/Kernel/Basic.lean index 2c9a8b8c7a5cb..3fc42e7dc57d2 100644 --- a/Mathlib/Probability/Kernel/Basic.lean +++ b/Mathlib/Probability/Kernel/Basic.lean @@ -3,387 +3,44 @@ Copyright (c) 2022 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ -import Mathlib.MeasureTheory.Integral.Bochner -import Mathlib.MeasureTheory.Measure.GiryMonad +import Mathlib.Probability.Kernel.Defs /-! -# Markov Kernels +# Basic kernels -A kernel from a measurable space `α` to another measurable space `β` is a measurable map -`α → MeasureTheory.Measure β`, where the measurable space instance on `measure β` is the one defined -in `MeasureTheory.Measure.instMeasurableSpace`. That is, a kernel `κ` verifies that for all -measurable sets `s` of `β`, `a ↦ κ a s` is measurable. +This file contains basic results about kernels in general and definitions of some particular +kernels. ## Main definitions -Classes of kernels: -* `ProbabilityTheory.Kernel α β`: kernels from `α` to `β`. -* `ProbabilityTheory.IsMarkovKernel κ`: a kernel from `α` to `β` is said to be a Markov kernel - if for all `a : α`, `k a` is a probability measure. -* `ProbabilityTheory.IsZeroOrMarkovKernel κ`: a kernel from `α` to `β` which is zero or - a Markov kernel. -* `ProbabilityTheory.IsFiniteKernel κ`: a kernel from `α` to `β` is said to be finite if there - exists `C : ℝ≥0∞` such that `C < ∞` and for all `a : α`, `κ a univ ≤ C`. This implies in - particular that all measures in the image of `κ` are finite, but is stronger since it requires a - uniform bound. This stronger condition is necessary to ensure that the composition of two finite - kernels is finite. -* `ProbabilityTheory.IsSFiniteKernel κ`: a kernel is called s-finite if it is a countable - sum of finite kernels. - -Particular kernels: * `ProbabilityTheory.Kernel.deterministic (f : α → β) (hf : Measurable f)`: kernel `a ↦ Measure.dirac (f a)`. * `ProbabilityTheory.Kernel.const α (μβ : measure β)`: constant kernel `a ↦ μβ`. * `ProbabilityTheory.Kernel.restrict κ (hs : MeasurableSet s)`: kernel for which the image of `a : α` is `(κ a).restrict s`. Integral: `∫⁻ b, f b ∂(κ.restrict hs a) = ∫⁻ b in s, f b ∂(κ a)` +* `ProbabilityTheory.Kernel.comapRight`: Kernel with value `(κ a).comap f`, + for a measurable embedding `f`. That is, for a measurable set `t : Set β`, + `ProbabilityTheory.Kernel.comapRight κ hf a t = κ a (f '' t)` +* `ProbabilityTheory.Kernel.piecewise (hs : MeasurableSet s) κ η`: the kernel equal to `κ` + on the measurable set `s` and to `η` on its complement. ## Main statements -* `ProbabilityTheory.Kernel.ext_fun`: if `∫⁻ b, f b ∂(κ a) = ∫⁻ b, f b ∂(η a)` for all measurable - functions `f` and all `a`, then the two kernels `κ` and `η` are equal. - -/ +assert_not_exists MeasureTheory.integral open MeasureTheory -open scoped MeasureTheory ENNReal NNReal +open scoped ENNReal namespace ProbabilityTheory -/-- A kernel from a measurable space `α` to another measurable space `β` is a measurable function -`κ : α → Measure β`. The measurable space structure on `MeasureTheory.Measure β` is given by -`MeasureTheory.Measure.instMeasurableSpace`. A map `κ : α → MeasureTheory.Measure β` is measurable -iff `∀ s : Set β, MeasurableSet s → Measurable (fun a ↦ κ a s)`. -/ -structure Kernel (α β : Type*) [MeasurableSpace α] [MeasurableSpace β] where - /-- The underlying function of a kernel. - - Do not use this function directly. Instead use the coercion coming from the `DFunLike` - instance. -/ - toFun : α → Measure β - /-- A kernel is a measurable map. - - Do not use this lemma directly. Use `Kernel.measurable` instead. -/ - measurable' : Measurable toFun - -@[deprecated (since := "2024-07-22")] alias kernel := Kernel - -/-- Notation for `Kernel` with respect to a non-standard σ-algebra in the domain. -/ -scoped notation "Kernel[" mα "]" α:arg β:arg => @Kernel α β mα _ - -/-- Notation for `Kernel` with respect to a non-standard σ-algebra in the domain and codomain. -/ -scoped notation "Kernel[" mα ", " mβ "]" α:arg β:arg => @Kernel α β mα mβ - -variable {α β ι : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} - -namespace Kernel - -instance instFunLike : FunLike (Kernel α β) α (Measure β) where - coe := toFun - coe_injective' f g h := by cases f; cases g; congr - -lemma measurable (κ : Kernel α β) : Measurable κ := κ.measurable' -@[simp, norm_cast] lemma coe_mk (f : α → Measure β) (hf) : mk f hf = f := rfl - -initialize_simps_projections Kernel (toFun → apply) - -instance instZero : Zero (Kernel α β) where zero := ⟨0, measurable_zero⟩ -noncomputable instance instAdd : Add (Kernel α β) where add κ η := ⟨κ + η, κ.2.add η.2⟩ -noncomputable instance instSMulNat : SMul ℕ (Kernel α β) where - smul n κ := ⟨n • κ, (measurable_const (a := n)).smul κ.2⟩ - -@[simp, norm_cast] lemma coe_zero : ⇑(0 : Kernel α β) = 0 := rfl -@[simp, norm_cast] lemma coe_add (κ η : Kernel α β) : ⇑(κ + η) = κ + η := rfl -@[simp, norm_cast] lemma coe_nsmul (n : ℕ) (κ : Kernel α β) : ⇑(n • κ) = n • κ := rfl - -@[simp] lemma zero_apply (a : α) : (0 : Kernel α β) a = 0 := rfl -@[simp] lemma add_apply (κ η : Kernel α β) (a : α) : (κ + η) a = κ a + η a := rfl -@[simp] lemma nsmul_apply (n : ℕ) (κ : Kernel α β) (a : α) : (n • κ) a = n • κ a := rfl - -noncomputable instance instAddCommMonoid : AddCommMonoid (Kernel α β) := - DFunLike.coe_injective.addCommMonoid _ coe_zero coe_add (by intros; rfl) - -instance instPartialOrder : PartialOrder (Kernel α β) := .lift _ DFunLike.coe_injective - -instance instCovariantAddLE {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] : - CovariantClass (Kernel α β) (Kernel α β) (· + ·) (· ≤ ·) := - ⟨fun _ _ _ hμ a ↦ add_le_add_left (hμ a) _⟩ - -noncomputable -instance instOrderBot {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] : - OrderBot (Kernel α β) where - bot := 0 - bot_le κ a := by simp only [coe_zero, Pi.zero_apply, Measure.zero_le] - -/-- Coercion to a function as an additive monoid homomorphism. -/ -def coeAddHom (α β : Type*) [MeasurableSpace α] [MeasurableSpace β] : - Kernel α β →+ α → Measure β where - toFun := (⇑) - map_zero' := coe_zero - map_add' := coe_add - -@[simp] -theorem coe_finset_sum (I : Finset ι) (κ : ι → Kernel α β) : ⇑(∑ i ∈ I, κ i) = ∑ i ∈ I, ⇑(κ i) := - map_sum (coeAddHom α β) _ _ - -theorem finset_sum_apply (I : Finset ι) (κ : ι → Kernel α β) (a : α) : - (∑ i ∈ I, κ i) a = ∑ i ∈ I, κ i a := by rw [coe_finset_sum, Finset.sum_apply] - -theorem finset_sum_apply' (I : Finset ι) (κ : ι → Kernel α β) (a : α) (s : Set β) : - (∑ i ∈ I, κ i) a s = ∑ i ∈ I, κ i a s := by rw [finset_sum_apply, Measure.finset_sum_apply] - -end Kernel - -/-- A kernel is a Markov kernel if every measure in its image is a probability measure. -/ -class IsMarkovKernel (κ : Kernel α β) : Prop where - isProbabilityMeasure : ∀ a, IsProbabilityMeasure (κ a) - -/-- A class for kernels which are zero or a Markov kernel. -/ -class IsZeroOrMarkovKernel (κ : Kernel α β) : Prop where - eq_zero_or_isMarkovKernel' : κ = 0 ∨ IsMarkovKernel κ - -/-- A kernel is finite if every measure in its image is finite, with a uniform bound. -/ -class IsFiniteKernel (κ : Kernel α β) : Prop where - exists_univ_le : ∃ C : ℝ≥0∞, C < ∞ ∧ ∀ a, κ a Set.univ ≤ C - -theorem eq_zero_or_isMarkovKernel - (κ : Kernel α β) [h : IsZeroOrMarkovKernel κ] : - κ = 0 ∨ IsMarkovKernel κ := - h.eq_zero_or_isMarkovKernel' - -/-- A constant `C : ℝ≥0∞` such that `C < ∞` (`ProbabilityTheory.IsFiniteKernel.bound_lt_top κ`) and -for all `a : α` and `s : Set β`, `κ a s ≤ C` (`ProbabilityTheory.Kernel.measure_le_bound κ a s`). - -Porting note (#11215): TODO: does it make sense to --- make `ProbabilityTheory.IsFiniteKernel.bound` the least possible bound? --- Should it be an `NNReal` number? -/ -noncomputable def IsFiniteKernel.bound (κ : Kernel α β) [h : IsFiniteKernel κ] : ℝ≥0∞ := - h.exists_univ_le.choose - -theorem IsFiniteKernel.bound_lt_top (κ : Kernel α β) [h : IsFiniteKernel κ] : - IsFiniteKernel.bound κ < ∞ := - h.exists_univ_le.choose_spec.1 - -theorem IsFiniteKernel.bound_ne_top (κ : Kernel α β) [IsFiniteKernel κ] : - IsFiniteKernel.bound κ ≠ ∞ := - (IsFiniteKernel.bound_lt_top κ).ne - -theorem Kernel.measure_le_bound (κ : Kernel α β) [h : IsFiniteKernel κ] (a : α) (s : Set β) : - κ a s ≤ IsFiniteKernel.bound κ := - (measure_mono (Set.subset_univ s)).trans (h.exists_univ_le.choose_spec.2 a) - -instance isFiniteKernel_zero (α β : Type*) {mα : MeasurableSpace α} {mβ : MeasurableSpace β} : - IsFiniteKernel (0 : Kernel α β) := - ⟨⟨0, ENNReal.coe_lt_top, fun _ => by - simp only [Kernel.zero_apply, Measure.coe_zero, Pi.zero_apply, le_zero_iff]⟩⟩ - -instance IsFiniteKernel.add (κ η : Kernel α β) [IsFiniteKernel κ] [IsFiniteKernel η] : - IsFiniteKernel (κ + η) := by - refine ⟨⟨IsFiniteKernel.bound κ + IsFiniteKernel.bound η, - ENNReal.add_lt_top.mpr ⟨IsFiniteKernel.bound_lt_top κ, IsFiniteKernel.bound_lt_top η⟩, - fun a => ?_⟩⟩ - exact add_le_add (Kernel.measure_le_bound _ _ _) (Kernel.measure_le_bound _ _ _) - -lemma isFiniteKernel_of_le {κ ν : Kernel α β} [hν : IsFiniteKernel ν] (hκν : κ ≤ ν) : - IsFiniteKernel κ := by - refine ⟨hν.bound, hν.bound_lt_top, fun a ↦ (hκν _ _).trans (Kernel.measure_le_bound ν a Set.univ)⟩ - -variable {κ : Kernel α β} - -instance IsMarkovKernel.is_probability_measure' [IsMarkovKernel κ] (a : α) : - IsProbabilityMeasure (κ a) := - IsMarkovKernel.isProbabilityMeasure a - -instance : IsZeroOrMarkovKernel (0 : Kernel α β) := ⟨Or.inl rfl⟩ - -instance (priority := 100) IsMarkovKernel.IsZeroOrMarkovKernel [h : IsMarkovKernel κ] : - IsZeroOrMarkovKernel κ := ⟨Or.inr h⟩ - -instance (priority := 100) IsZeroOrMarkovKernel.isZeroOrProbabilityMeasure - [IsZeroOrMarkovKernel κ] (a : α) : IsZeroOrProbabilityMeasure (κ a) := by - rcases eq_zero_or_isMarkovKernel κ with rfl | h' - · simp only [Kernel.zero_apply] - infer_instance - · infer_instance - -instance IsFiniteKernel.isFiniteMeasure [IsFiniteKernel κ] (a : α) : IsFiniteMeasure (κ a) := - ⟨(Kernel.measure_le_bound κ a Set.univ).trans_lt (IsFiniteKernel.bound_lt_top κ)⟩ - -instance (priority := 100) IsZeroOrMarkovKernel.isFiniteKernel [h : IsZeroOrMarkovKernel κ] : - IsFiniteKernel κ := by - rcases eq_zero_or_isMarkovKernel κ with rfl | _h' - · infer_instance - · exact ⟨⟨1, ENNReal.one_lt_top, fun _ => prob_le_one⟩⟩ +variable {α β ι : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} {κ : Kernel α β} namespace Kernel -@[ext] -theorem ext {η : Kernel α β} (h : ∀ a, κ a = η a) : κ = η := DFunLike.ext _ _ h - -theorem ext_iff' {η : Kernel α β} : - κ = η ↔ ∀ a s, MeasurableSet s → κ a s = η a s := by - simp_rw [Kernel.ext_iff, Measure.ext_iff] - -theorem ext_fun {η : Kernel α β} (h : ∀ a f, Measurable f → ∫⁻ b, f b ∂κ a = ∫⁻ b, f b ∂η a) : - κ = η := by - ext a s hs - specialize h a (s.indicator fun _ => 1) (Measurable.indicator measurable_const hs) - simp_rw [lintegral_indicator_const hs, one_mul] at h - rw [h] - -theorem ext_fun_iff {η : Kernel α β} : - κ = η ↔ ∀ a f, Measurable f → ∫⁻ b, f b ∂κ a = ∫⁻ b, f b ∂η a := - ⟨fun h a f _ => by rw [h], ext_fun⟩ - -protected theorem measurable_coe (κ : Kernel α β) {s : Set β} (hs : MeasurableSet s) : - Measurable fun a => κ a s := - (Measure.measurable_coe hs).comp κ.measurable - -lemma apply_congr_of_mem_measurableAtom (κ : Kernel α β) {y' y : α} (hy' : y' ∈ measurableAtom y) : - κ y' = κ y := by - ext s hs - exact mem_of_mem_measurableAtom hy' (κ.measurable_coe hs (measurableSet_singleton (κ y s))) rfl - -lemma IsFiniteKernel.integrable (μ : Measure α) [IsFiniteMeasure μ] - (κ : Kernel α β) [IsFiniteKernel κ] {s : Set β} (hs : MeasurableSet s) : - Integrable (fun x => (κ x s).toReal) μ := by - refine Integrable.mono' (integrable_const (IsFiniteKernel.bound κ).toReal) - ((κ.measurable_coe hs).ennreal_toReal.aestronglyMeasurable) - (ae_of_all μ fun x => ?_) - rw [Real.norm_eq_abs, abs_of_nonneg ENNReal.toReal_nonneg, - ENNReal.toReal_le_toReal (measure_ne_top _ _) (IsFiniteKernel.bound_ne_top _)] - exact Kernel.measure_le_bound _ _ _ - -lemma IsMarkovKernel.integrable (μ : Measure α) [IsFiniteMeasure μ] - (κ : Kernel α β) [IsMarkovKernel κ] {s : Set β} (hs : MeasurableSet s) : - Integrable (fun x => (κ x s).toReal) μ := - IsFiniteKernel.integrable μ κ hs - -lemma integral_congr_ae₂ {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {f g : α → β → E} - {μ : Measure α} (h : ∀ᵐ a ∂μ, f a =ᵐ[κ a] g a) : - ∫ a, ∫ b, f a b ∂(κ a) ∂μ = ∫ a, ∫ b, g a b ∂(κ a) ∂μ := by - apply integral_congr_ae - filter_upwards [h] with _ ha - apply integral_congr_ae - filter_upwards [ha] with _ hb using hb - -section Sum - -/-- Sum of an indexed family of kernels. -/ -protected noncomputable def sum [Countable ι] (κ : ι → Kernel α β) : Kernel α β where - toFun a := Measure.sum fun n => κ n a - measurable' := by - refine Measure.measurable_of_measurable_coe _ fun s hs => ?_ - simp_rw [Measure.sum_apply _ hs] - exact Measurable.ennreal_tsum fun n => Kernel.measurable_coe (κ n) hs - -theorem sum_apply [Countable ι] (κ : ι → Kernel α β) (a : α) : - Kernel.sum κ a = Measure.sum fun n => κ n a := - rfl - -theorem sum_apply' [Countable ι] (κ : ι → Kernel α β) (a : α) {s : Set β} (hs : MeasurableSet s) : - Kernel.sum κ a s = ∑' n, κ n a s := by rw [sum_apply κ a, Measure.sum_apply _ hs] - -@[simp] -theorem sum_zero [Countable ι] : (Kernel.sum fun _ : ι => (0 : Kernel α β)) = 0 := by - ext a s hs - rw [sum_apply' _ a hs] - simp only [zero_apply, Measure.coe_zero, Pi.zero_apply, tsum_zero] - -theorem sum_comm [Countable ι] (κ : ι → ι → Kernel α β) : - (Kernel.sum fun n => Kernel.sum (κ n)) = Kernel.sum fun m => Kernel.sum fun n => κ n m := by - ext a s; simp_rw [sum_apply]; rw [Measure.sum_comm] - -@[simp] -theorem sum_fintype [Fintype ι] (κ : ι → Kernel α β) : Kernel.sum κ = ∑ i, κ i := by - ext a s hs - simp only [sum_apply' κ a hs, finset_sum_apply' _ κ a s, tsum_fintype] - -theorem sum_add [Countable ι] (κ η : ι → Kernel α β) : - (Kernel.sum fun n => κ n + η n) = Kernel.sum κ + Kernel.sum η := by - ext a s hs - simp only [coe_add, Pi.add_apply, sum_apply, Measure.sum_apply _ hs, Pi.add_apply, - Measure.coe_add, tsum_add ENNReal.summable ENNReal.summable] - -end Sum - -section SFinite - -/-- A kernel is s-finite if it can be written as the sum of countably many finite kernels. -/ -class _root_.ProbabilityTheory.IsSFiniteKernel (κ : Kernel α β) : Prop where - tsum_finite : ∃ κs : ℕ → Kernel α β, (∀ n, IsFiniteKernel (κs n)) ∧ κ = Kernel.sum κs - -instance (priority := 100) IsFiniteKernel.isSFiniteKernel [h : IsFiniteKernel κ] : - IsSFiniteKernel κ := - ⟨⟨fun n => if n = 0 then κ else 0, fun n => by - simp only; split_ifs - · exact h - · infer_instance, by - ext a s hs - rw [Kernel.sum_apply' _ _ hs] - have : (fun i => ((ite (i = 0) κ 0) a) s) = fun i => ite (i = 0) (κ a s) 0 := by - ext1 i; split_ifs <;> rfl - rw [this, tsum_ite_eq]⟩⟩ - -/-- A sequence of finite kernels such that `κ = ProbabilityTheory.Kernel.sum (seq κ)`. See -`ProbabilityTheory.Kernel.isFiniteKernel_seq` and `ProbabilityTheory.Kernel.kernel_sum_seq`. -/ -noncomputable def seq (κ : Kernel α β) [h : IsSFiniteKernel κ] : ℕ → Kernel α β := - h.tsum_finite.choose - -theorem kernel_sum_seq (κ : Kernel α β) [h : IsSFiniteKernel κ] : Kernel.sum (seq κ) = κ := - h.tsum_finite.choose_spec.2.symm - -theorem measure_sum_seq (κ : Kernel α β) [h : IsSFiniteKernel κ] (a : α) : - (Measure.sum fun n => seq κ n a) = κ a := by rw [← Kernel.sum_apply, kernel_sum_seq κ] - -instance isFiniteKernel_seq (κ : Kernel α β) [h : IsSFiniteKernel κ] (n : ℕ) : - IsFiniteKernel (Kernel.seq κ n) := - h.tsum_finite.choose_spec.1 n - -instance _root_.ProbabilityTheory.IsSFiniteKernel.sFinite [IsSFiniteKernel κ] (a : α) : - SFinite (κ a) := - ⟨⟨fun n ↦ seq κ n a, inferInstance, (measure_sum_seq κ a).symm⟩⟩ - -instance IsSFiniteKernel.add (κ η : Kernel α β) [IsSFiniteKernel κ] [IsSFiniteKernel η] : - IsSFiniteKernel (κ + η) := by - refine ⟨⟨fun n => seq κ n + seq η n, fun n => inferInstance, ?_⟩⟩ - rw [sum_add, kernel_sum_seq κ, kernel_sum_seq η] - -theorem IsSFiniteKernel.finset_sum {κs : ι → Kernel α β} (I : Finset ι) - (h : ∀ i ∈ I, IsSFiniteKernel (κs i)) : IsSFiniteKernel (∑ i ∈ I, κs i) := by - classical - induction' I using Finset.induction with i I hi_nmem_I h_ind h - · rw [Finset.sum_empty]; infer_instance - · rw [Finset.sum_insert hi_nmem_I] - haveI : IsSFiniteKernel (κs i) := h i (Finset.mem_insert_self _ _) - have : IsSFiniteKernel (∑ x ∈ I, κs x) := - h_ind fun i hiI => h i (Finset.mem_insert_of_mem hiI) - exact IsSFiniteKernel.add _ _ - -theorem isSFiniteKernel_sum_of_denumerable [Denumerable ι] {κs : ι → Kernel α β} - (hκs : ∀ n, IsSFiniteKernel (κs n)) : IsSFiniteKernel (Kernel.sum κs) := by - let e : ℕ ≃ ι × ℕ := (Denumerable.eqv (ι × ℕ)).symm - refine ⟨⟨fun n => seq (κs (e n).1) (e n).2, inferInstance, ?_⟩⟩ - have hκ_eq : Kernel.sum κs = Kernel.sum fun n => Kernel.sum (seq (κs n)) := by - simp_rw [kernel_sum_seq] - ext a s hs - rw [hκ_eq] - simp_rw [Kernel.sum_apply' _ _ hs] - change (∑' i, ∑' m, seq (κs i) m a s) = ∑' n, (fun im : ι × ℕ => seq (κs im.fst) im.snd a s) (e n) - rw [e.tsum_eq (fun im : ι × ℕ => seq (κs im.fst) im.snd a s), - tsum_prod' ENNReal.summable fun _ => ENNReal.summable] - -theorem isSFiniteKernel_sum [Countable ι] {κs : ι → Kernel α β} - (hκs : ∀ n, IsSFiniteKernel (κs n)) : IsSFiniteKernel (Kernel.sum κs) := by - cases fintypeOrInfinite ι - · rw [sum_fintype] - exact IsSFiniteKernel.finset_sum Finset.univ fun i _ => hκs i - cases nonempty_denumerable ι - exact isSFiniteKernel_sum_of_denumerable hκs - -end SFinite - section Deterministic /-- Kernel which to `a` associates the dirac measure at `f a`. This is a Markov kernel. -/ @@ -434,36 +91,6 @@ theorem setLIntegral_deterministic {f : β → ℝ≥0∞} {g : α → β} {a : @[deprecated (since := "2024-06-29")] alias set_lintegral_deterministic := setLIntegral_deterministic -theorem integral_deterministic' {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - [CompleteSpace E] {f : β → E} {g : α → β} {a : α} (hg : Measurable g) - (hf : StronglyMeasurable f) : ∫ x, f x ∂deterministic g hg a = f (g a) := by - rw [deterministic_apply, integral_dirac' _ _ hf] - -@[simp] -theorem integral_deterministic {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - [CompleteSpace E] {f : β → E} {g : α → β} {a : α} (hg : Measurable g) - [MeasurableSingletonClass β] : ∫ x, f x ∂deterministic g hg a = f (g a) := by - rw [deterministic_apply, integral_dirac _ (g a)] - -theorem setIntegral_deterministic' {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - [CompleteSpace E] {f : β → E} {g : α → β} {a : α} (hg : Measurable g) - (hf : StronglyMeasurable f) {s : Set β} (hs : MeasurableSet s) [Decidable (g a ∈ s)] : - ∫ x in s, f x ∂deterministic g hg a = if g a ∈ s then f (g a) else 0 := by - rw [deterministic_apply, setIntegral_dirac' hf _ hs] - -@[deprecated (since := "2024-04-17")] -alias set_integral_deterministic' := setIntegral_deterministic' - -@[simp] -theorem setIntegral_deterministic {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - [CompleteSpace E] {f : β → E} {g : α → β} {a : α} (hg : Measurable g) - [MeasurableSingletonClass β] (s : Set β) [Decidable (g a ∈ s)] : - ∫ x in s, f x ∂deterministic g hg a = if g a ∈ s then f (g a) else 0 := by - rw [deterministic_apply, setIntegral_dirac f _ s] - -@[deprecated (since := "2024-04-17")] -alias set_integral_deterministic := setIntegral_deterministic - end Deterministic section Const @@ -525,19 +152,6 @@ theorem setLIntegral_const {f : β → ℝ≥0∞} {μ : Measure β} {a : α} {s @[deprecated (since := "2024-06-29")] alias set_lintegral_const := setLIntegral_const -@[simp] -theorem integral_const {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - {f : β → E} {μ : Measure β} {a : α} : ∫ x, f x ∂const α μ a = ∫ x, f x ∂μ := by - rw [const_apply] - -@[simp] -theorem setIntegral_const {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - {f : β → E} {μ : Measure β} {a : α} {s : Set β} : - ∫ x in s, f x ∂const α μ a = ∫ x in s, f x ∂μ := by rw [const_apply] - -@[deprecated (since := "2024-04-17")] -alias set_integral_const := setIntegral_const - end Const /-- In a countable space with measurable singletons, every function `α → MeasureTheory.Measure β` @@ -584,14 +198,6 @@ theorem setLIntegral_restrict (κ : Kernel α β) (hs : MeasurableSet s) (a : α @[deprecated (since := "2024-06-29")] alias set_lintegral_restrict := setLIntegral_restrict -@[simp] -theorem setIntegral_restrict {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - {f : β → E} {a : α} (hs : MeasurableSet s) (t : Set β) : - ∫ x in t, f x ∂κ.restrict hs a = ∫ x in t ∩ s, f x ∂κ a := by - rw [restrict_apply, Measure.restrict_restrict' hs] - -@[deprecated (since := "2024-04-17")] -alias set_integral_restrict := setIntegral_restrict instance IsFiniteKernel.restrict (κ : Kernel α β) [IsFiniteKernel κ] (hs : MeasurableSet s) : IsFiniteKernel (κ.restrict hs) := by @@ -716,20 +322,6 @@ theorem setLIntegral_piecewise (a : α) (g : β → ℝ≥0∞) (t : Set β) : @[deprecated (since := "2024-06-29")] alias set_lintegral_piecewise := setLIntegral_piecewise -theorem integral_piecewise {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - (a : α) (g : β → E) : - ∫ b, g b ∂piecewise hs κ η a = if a ∈ s then ∫ b, g b ∂κ a else ∫ b, g b ∂η a := by - simp_rw [piecewise_apply]; split_ifs <;> rfl - -theorem setIntegral_piecewise {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - (a : α) (g : β → E) (t : Set β) : - ∫ b in t, g b ∂piecewise hs κ η a = - if a ∈ s then ∫ b in t, g b ∂κ a else ∫ b in t, g b ∂η a := by - simp_rw [piecewise_apply]; split_ifs <;> rfl - -@[deprecated (since := "2024-04-17")] -alias set_integral_piecewise := setIntegral_piecewise - end Piecewise lemma exists_ae_eq_isMarkovKernel {μ : Measure α} diff --git a/Mathlib/Probability/Kernel/Defs.lean b/Mathlib/Probability/Kernel/Defs.lean new file mode 100644 index 0000000000000..707e45278f5bc --- /dev/null +++ b/Mathlib/Probability/Kernel/Defs.lean @@ -0,0 +1,354 @@ +/- +Copyright (c) 2022 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne +-/ +import Mathlib.MeasureTheory.Measure.GiryMonad + +/-! +# Markov Kernels + +A kernel from a measurable space `α` to another measurable space `β` is a measurable map +`α → MeasureTheory.Measure β`, where the measurable space instance on `measure β` is the one defined +in `MeasureTheory.Measure.instMeasurableSpace`. That is, a kernel `κ` verifies that for all +measurable sets `s` of `β`, `a ↦ κ a s` is measurable. + +## Main definitions + +Classes of kernels: +* `ProbabilityTheory.Kernel α β`: kernels from `α` to `β`. +* `ProbabilityTheory.IsMarkovKernel κ`: a kernel from `α` to `β` is said to be a Markov kernel + if for all `a : α`, `k a` is a probability measure. +* `ProbabilityTheory.IsZeroOrMarkovKernel κ`: a kernel from `α` to `β` which is zero or + a Markov kernel. +* `ProbabilityTheory.IsFiniteKernel κ`: a kernel from `α` to `β` is said to be finite if there + exists `C : ℝ≥0∞` such that `C < ∞` and for all `a : α`, `κ a univ ≤ C`. This implies in + particular that all measures in the image of `κ` are finite, but is stronger since it requires a + uniform bound. This stronger condition is necessary to ensure that the composition of two finite + kernels is finite. +* `ProbabilityTheory.IsSFiniteKernel κ`: a kernel is called s-finite if it is a countable + sum of finite kernels. + +## Main statements + +* `ProbabilityTheory.Kernel.ext_fun`: if `∫⁻ b, f b ∂(κ a) = ∫⁻ b, f b ∂(η a)` for all measurable + functions `f` and all `a`, then the two kernels `κ` and `η` are equal. + +-/ + +assert_not_exists MeasureTheory.integral + +open MeasureTheory + +open scoped ENNReal + +namespace ProbabilityTheory + +/-- A kernel from a measurable space `α` to another measurable space `β` is a measurable function +`κ : α → Measure β`. The measurable space structure on `MeasureTheory.Measure β` is given by +`MeasureTheory.Measure.instMeasurableSpace`. A map `κ : α → MeasureTheory.Measure β` is measurable +iff `∀ s : Set β, MeasurableSet s → Measurable (fun a ↦ κ a s)`. -/ +structure Kernel (α β : Type*) [MeasurableSpace α] [MeasurableSpace β] where + /-- The underlying function of a kernel. + + Do not use this function directly. Instead use the coercion coming from the `DFunLike` + instance. -/ + toFun : α → Measure β + /-- A kernel is a measurable map. + + Do not use this lemma directly. Use `Kernel.measurable` instead. -/ + measurable' : Measurable toFun + +@[deprecated (since := "2024-07-22")] alias kernel := Kernel + +/-- Notation for `Kernel` with respect to a non-standard σ-algebra in the domain. -/ +scoped notation "Kernel[" mα "]" α:arg β:arg => @Kernel α β mα _ + +/-- Notation for `Kernel` with respect to a non-standard σ-algebra in the domain and codomain. -/ +scoped notation "Kernel[" mα ", " mβ "]" α:arg β:arg => @Kernel α β mα mβ + +variable {α β ι : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} + +namespace Kernel + +instance instFunLike : FunLike (Kernel α β) α (Measure β) where + coe := toFun + coe_injective' f g h := by cases f; cases g; congr + +lemma measurable (κ : Kernel α β) : Measurable κ := κ.measurable' +@[simp, norm_cast] lemma coe_mk (f : α → Measure β) (hf) : mk f hf = f := rfl + +initialize_simps_projections Kernel (toFun → apply) + +instance instZero : Zero (Kernel α β) where zero := ⟨0, measurable_zero⟩ +noncomputable instance instAdd : Add (Kernel α β) where add κ η := ⟨κ + η, κ.2.add η.2⟩ +noncomputable instance instSMulNat : SMul ℕ (Kernel α β) where + smul n κ := ⟨n • κ, (measurable_const (a := n)).smul κ.2⟩ + +@[simp, norm_cast] lemma coe_zero : ⇑(0 : Kernel α β) = 0 := rfl +@[simp, norm_cast] lemma coe_add (κ η : Kernel α β) : ⇑(κ + η) = κ + η := rfl +@[simp, norm_cast] lemma coe_nsmul (n : ℕ) (κ : Kernel α β) : ⇑(n • κ) = n • κ := rfl + +@[simp] lemma zero_apply (a : α) : (0 : Kernel α β) a = 0 := rfl +@[simp] lemma add_apply (κ η : Kernel α β) (a : α) : (κ + η) a = κ a + η a := rfl +@[simp] lemma nsmul_apply (n : ℕ) (κ : Kernel α β) (a : α) : (n • κ) a = n • κ a := rfl + +noncomputable instance instAddCommMonoid : AddCommMonoid (Kernel α β) := + DFunLike.coe_injective.addCommMonoid _ coe_zero coe_add (by intros; rfl) + +instance instPartialOrder : PartialOrder (Kernel α β) := .lift _ DFunLike.coe_injective + +instance instCovariantAddLE {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] : + CovariantClass (Kernel α β) (Kernel α β) (· + ·) (· ≤ ·) := + ⟨fun _ _ _ hμ a ↦ add_le_add_left (hμ a) _⟩ + +noncomputable +instance instOrderBot {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] : + OrderBot (Kernel α β) where + bot := 0 + bot_le κ a := by simp only [coe_zero, Pi.zero_apply, Measure.zero_le] + +/-- Coercion to a function as an additive monoid homomorphism. -/ +def coeAddHom (α β : Type*) [MeasurableSpace α] [MeasurableSpace β] : + Kernel α β →+ α → Measure β where + toFun := (⇑) + map_zero' := coe_zero + map_add' := coe_add + +@[simp] +theorem coe_finset_sum (I : Finset ι) (κ : ι → Kernel α β) : ⇑(∑ i ∈ I, κ i) = ∑ i ∈ I, ⇑(κ i) := + map_sum (coeAddHom α β) _ _ + +theorem finset_sum_apply (I : Finset ι) (κ : ι → Kernel α β) (a : α) : + (∑ i ∈ I, κ i) a = ∑ i ∈ I, κ i a := by rw [coe_finset_sum, Finset.sum_apply] + +theorem finset_sum_apply' (I : Finset ι) (κ : ι → Kernel α β) (a : α) (s : Set β) : + (∑ i ∈ I, κ i) a s = ∑ i ∈ I, κ i a s := by rw [finset_sum_apply, Measure.finset_sum_apply] + +end Kernel + +/-- A kernel is a Markov kernel if every measure in its image is a probability measure. -/ +class IsMarkovKernel (κ : Kernel α β) : Prop where + isProbabilityMeasure : ∀ a, IsProbabilityMeasure (κ a) + +/-- A class for kernels which are zero or a Markov kernel. -/ +class IsZeroOrMarkovKernel (κ : Kernel α β) : Prop where + eq_zero_or_isMarkovKernel' : κ = 0 ∨ IsMarkovKernel κ + +/-- A kernel is finite if every measure in its image is finite, with a uniform bound. -/ +class IsFiniteKernel (κ : Kernel α β) : Prop where + exists_univ_le : ∃ C : ℝ≥0∞, C < ∞ ∧ ∀ a, κ a Set.univ ≤ C + +theorem eq_zero_or_isMarkovKernel + (κ : Kernel α β) [h : IsZeroOrMarkovKernel κ] : + κ = 0 ∨ IsMarkovKernel κ := + h.eq_zero_or_isMarkovKernel' + +/-- A constant `C : ℝ≥0∞` such that `C < ∞` (`ProbabilityTheory.IsFiniteKernel.bound_lt_top κ`) and +for all `a : α` and `s : Set β`, `κ a s ≤ C` (`ProbabilityTheory.Kernel.measure_le_bound κ a s`). + +Porting note (#11215): TODO: does it make sense to +-- make `ProbabilityTheory.IsFiniteKernel.bound` the least possible bound? +-- Should it be an `NNReal` number? -/ +noncomputable def IsFiniteKernel.bound (κ : Kernel α β) [h : IsFiniteKernel κ] : ℝ≥0∞ := + h.exists_univ_le.choose + +theorem IsFiniteKernel.bound_lt_top (κ : Kernel α β) [h : IsFiniteKernel κ] : + IsFiniteKernel.bound κ < ∞ := + h.exists_univ_le.choose_spec.1 + +theorem IsFiniteKernel.bound_ne_top (κ : Kernel α β) [IsFiniteKernel κ] : + IsFiniteKernel.bound κ ≠ ∞ := + (IsFiniteKernel.bound_lt_top κ).ne + +theorem Kernel.measure_le_bound (κ : Kernel α β) [h : IsFiniteKernel κ] (a : α) (s : Set β) : + κ a s ≤ IsFiniteKernel.bound κ := + (measure_mono (Set.subset_univ s)).trans (h.exists_univ_le.choose_spec.2 a) + +instance isFiniteKernel_zero (α β : Type*) {mα : MeasurableSpace α} {mβ : MeasurableSpace β} : + IsFiniteKernel (0 : Kernel α β) := + ⟨⟨0, ENNReal.coe_lt_top, fun _ => by + simp only [Kernel.zero_apply, Measure.coe_zero, Pi.zero_apply, le_zero_iff]⟩⟩ + +instance IsFiniteKernel.add (κ η : Kernel α β) [IsFiniteKernel κ] [IsFiniteKernel η] : + IsFiniteKernel (κ + η) := by + refine ⟨⟨IsFiniteKernel.bound κ + IsFiniteKernel.bound η, + ENNReal.add_lt_top.mpr ⟨IsFiniteKernel.bound_lt_top κ, IsFiniteKernel.bound_lt_top η⟩, + fun a => ?_⟩⟩ + exact add_le_add (Kernel.measure_le_bound _ _ _) (Kernel.measure_le_bound _ _ _) + +lemma isFiniteKernel_of_le {κ ν : Kernel α β} [hν : IsFiniteKernel ν] (hκν : κ ≤ ν) : + IsFiniteKernel κ := by + refine ⟨hν.bound, hν.bound_lt_top, fun a ↦ (hκν _ _).trans (Kernel.measure_le_bound ν a Set.univ)⟩ + +variable {κ η : Kernel α β} + +instance IsMarkovKernel.is_probability_measure' [IsMarkovKernel κ] (a : α) : + IsProbabilityMeasure (κ a) := + IsMarkovKernel.isProbabilityMeasure a + +instance : IsZeroOrMarkovKernel (0 : Kernel α β) := ⟨Or.inl rfl⟩ + +instance (priority := 100) IsMarkovKernel.IsZeroOrMarkovKernel [h : IsMarkovKernel κ] : + IsZeroOrMarkovKernel κ := ⟨Or.inr h⟩ + +instance (priority := 100) IsZeroOrMarkovKernel.isZeroOrProbabilityMeasure + [IsZeroOrMarkovKernel κ] (a : α) : IsZeroOrProbabilityMeasure (κ a) := by + rcases eq_zero_or_isMarkovKernel κ with rfl | h' + · simp only [Kernel.zero_apply] + infer_instance + · infer_instance + +instance IsFiniteKernel.isFiniteMeasure [IsFiniteKernel κ] (a : α) : IsFiniteMeasure (κ a) := + ⟨(Kernel.measure_le_bound κ a Set.univ).trans_lt (IsFiniteKernel.bound_lt_top κ)⟩ + +instance (priority := 100) IsZeroOrMarkovKernel.isFiniteKernel [h : IsZeroOrMarkovKernel κ] : + IsFiniteKernel κ := by + rcases eq_zero_or_isMarkovKernel κ with rfl | _h' + · infer_instance + · exact ⟨⟨1, ENNReal.one_lt_top, fun _ => prob_le_one⟩⟩ + +namespace Kernel + +@[ext] +theorem ext (h : ∀ a, κ a = η a) : κ = η := DFunLike.ext _ _ h + +theorem ext_iff' : κ = η ↔ ∀ a s, MeasurableSet s → κ a s = η a s := by + simp_rw [Kernel.ext_iff, Measure.ext_iff] + +theorem ext_fun (h : ∀ a f, Measurable f → ∫⁻ b, f b ∂κ a = ∫⁻ b, f b ∂η a) : + κ = η := by + ext a s hs + specialize h a (s.indicator fun _ => 1) (Measurable.indicator measurable_const hs) + simp_rw [lintegral_indicator_const hs, one_mul] at h + rw [h] + +theorem ext_fun_iff : κ = η ↔ ∀ a f, Measurable f → ∫⁻ b, f b ∂κ a = ∫⁻ b, f b ∂η a := + ⟨fun h a f _ => by rw [h], ext_fun⟩ + +protected theorem measurable_coe (κ : Kernel α β) {s : Set β} (hs : MeasurableSet s) : + Measurable fun a => κ a s := + (Measure.measurable_coe hs).comp κ.measurable + +lemma apply_congr_of_mem_measurableAtom (κ : Kernel α β) {y' y : α} (hy' : y' ∈ measurableAtom y) : + κ y' = κ y := by + ext s hs + exact mem_of_mem_measurableAtom hy' (κ.measurable_coe hs (measurableSet_singleton (κ y s))) rfl + +section Sum + +/-- Sum of an indexed family of kernels. -/ +protected noncomputable def sum [Countable ι] (κ : ι → Kernel α β) : Kernel α β where + toFun a := Measure.sum fun n => κ n a + measurable' := by + refine Measure.measurable_of_measurable_coe _ fun s hs => ?_ + simp_rw [Measure.sum_apply _ hs] + exact Measurable.ennreal_tsum fun n => Kernel.measurable_coe (κ n) hs + +theorem sum_apply [Countable ι] (κ : ι → Kernel α β) (a : α) : + Kernel.sum κ a = Measure.sum fun n => κ n a := + rfl + +theorem sum_apply' [Countable ι] (κ : ι → Kernel α β) (a : α) {s : Set β} (hs : MeasurableSet s) : + Kernel.sum κ a s = ∑' n, κ n a s := by rw [sum_apply κ a, Measure.sum_apply _ hs] + +@[simp] +theorem sum_zero [Countable ι] : (Kernel.sum fun _ : ι => (0 : Kernel α β)) = 0 := by + ext a s hs + rw [sum_apply' _ a hs] + simp only [zero_apply, Measure.coe_zero, Pi.zero_apply, tsum_zero] + +theorem sum_comm [Countable ι] (κ : ι → ι → Kernel α β) : + (Kernel.sum fun n => Kernel.sum (κ n)) = Kernel.sum fun m => Kernel.sum fun n => κ n m := by + ext a s; simp_rw [sum_apply]; rw [Measure.sum_comm] + +@[simp] +theorem sum_fintype [Fintype ι] (κ : ι → Kernel α β) : Kernel.sum κ = ∑ i, κ i := by + ext a s hs + simp only [sum_apply' κ a hs, finset_sum_apply' _ κ a s, tsum_fintype] + +theorem sum_add [Countable ι] (κ η : ι → Kernel α β) : + (Kernel.sum fun n => κ n + η n) = Kernel.sum κ + Kernel.sum η := by + ext a s hs + simp only [coe_add, Pi.add_apply, sum_apply, Measure.sum_apply _ hs, Pi.add_apply, + Measure.coe_add, tsum_add ENNReal.summable ENNReal.summable] + +end Sum + +section SFinite + +/-- A kernel is s-finite if it can be written as the sum of countably many finite kernels. -/ +class _root_.ProbabilityTheory.IsSFiniteKernel (κ : Kernel α β) : Prop where + tsum_finite : ∃ κs : ℕ → Kernel α β, (∀ n, IsFiniteKernel (κs n)) ∧ κ = Kernel.sum κs + +instance (priority := 100) IsFiniteKernel.isSFiniteKernel [h : IsFiniteKernel κ] : + IsSFiniteKernel κ := + ⟨⟨fun n => if n = 0 then κ else 0, fun n => by + simp only; split_ifs + · exact h + · infer_instance, by + ext a s hs + rw [Kernel.sum_apply' _ _ hs] + have : (fun i => ((ite (i = 0) κ 0) a) s) = fun i => ite (i = 0) (κ a s) 0 := by + ext1 i; split_ifs <;> rfl + rw [this, tsum_ite_eq]⟩⟩ + +/-- A sequence of finite kernels such that `κ = ProbabilityTheory.Kernel.sum (seq κ)`. See +`ProbabilityTheory.Kernel.isFiniteKernel_seq` and `ProbabilityTheory.Kernel.kernel_sum_seq`. -/ +noncomputable def seq (κ : Kernel α β) [h : IsSFiniteKernel κ] : ℕ → Kernel α β := + h.tsum_finite.choose + +theorem kernel_sum_seq (κ : Kernel α β) [h : IsSFiniteKernel κ] : Kernel.sum (seq κ) = κ := + h.tsum_finite.choose_spec.2.symm + +theorem measure_sum_seq (κ : Kernel α β) [h : IsSFiniteKernel κ] (a : α) : + (Measure.sum fun n => seq κ n a) = κ a := by rw [← Kernel.sum_apply, kernel_sum_seq κ] + +instance isFiniteKernel_seq (κ : Kernel α β) [h : IsSFiniteKernel κ] (n : ℕ) : + IsFiniteKernel (Kernel.seq κ n) := + h.tsum_finite.choose_spec.1 n + +instance _root_.ProbabilityTheory.IsSFiniteKernel.sFinite [IsSFiniteKernel κ] (a : α) : + SFinite (κ a) := + ⟨⟨fun n ↦ seq κ n a, inferInstance, (measure_sum_seq κ a).symm⟩⟩ + +instance IsSFiniteKernel.add (κ η : Kernel α β) [IsSFiniteKernel κ] [IsSFiniteKernel η] : + IsSFiniteKernel (κ + η) := by + refine ⟨⟨fun n => seq κ n + seq η n, fun n => inferInstance, ?_⟩⟩ + rw [sum_add, kernel_sum_seq κ, kernel_sum_seq η] + +theorem IsSFiniteKernel.finset_sum {κs : ι → Kernel α β} (I : Finset ι) + (h : ∀ i ∈ I, IsSFiniteKernel (κs i)) : IsSFiniteKernel (∑ i ∈ I, κs i) := by + classical + induction' I using Finset.induction with i I hi_nmem_I h_ind h + · rw [Finset.sum_empty]; infer_instance + · rw [Finset.sum_insert hi_nmem_I] + haveI : IsSFiniteKernel (κs i) := h i (Finset.mem_insert_self _ _) + have : IsSFiniteKernel (∑ x ∈ I, κs x) := + h_ind fun i hiI => h i (Finset.mem_insert_of_mem hiI) + exact IsSFiniteKernel.add _ _ + +theorem isSFiniteKernel_sum_of_denumerable [Denumerable ι] {κs : ι → Kernel α β} + (hκs : ∀ n, IsSFiniteKernel (κs n)) : IsSFiniteKernel (Kernel.sum κs) := by + let e : ℕ ≃ ι × ℕ := (Denumerable.eqv (ι × ℕ)).symm + refine ⟨⟨fun n => seq (κs (e n).1) (e n).2, inferInstance, ?_⟩⟩ + have hκ_eq : Kernel.sum κs = Kernel.sum fun n => Kernel.sum (seq (κs n)) := by + simp_rw [kernel_sum_seq] + ext a s hs + rw [hκ_eq] + simp_rw [Kernel.sum_apply' _ _ hs] + change (∑' i, ∑' m, seq (κs i) m a s) = ∑' n, (fun im : ι × ℕ => seq (κs im.fst) im.snd a s) (e n) + rw [e.tsum_eq (fun im : ι × ℕ => seq (κs im.fst) im.snd a s), + tsum_prod' ENNReal.summable fun _ => ENNReal.summable] + +theorem isSFiniteKernel_sum [Countable ι] {κs : ι → Kernel α β} + (hκs : ∀ n, IsSFiniteKernel (κs n)) : IsSFiniteKernel (Kernel.sum κs) := by + cases fintypeOrInfinite ι + · rw [sum_fintype] + exact IsSFiniteKernel.finset_sum Finset.univ fun i _ => hκs i + cases nonempty_denumerable ι + exact isSFiniteKernel_sum_of_denumerable hκs + +end SFinite +end Kernel +end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/Integral.lean b/Mathlib/Probability/Kernel/Integral.lean new file mode 100644 index 0000000000000..f259203acbe03 --- /dev/null +++ b/Mathlib/Probability/Kernel/Integral.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2022 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne +-/ +import Mathlib.MeasureTheory.Integral.Bochner +import Mathlib.Probability.Kernel.Basic + +/-! +# Bochner integrals of kernels + +-/ + +open MeasureTheory + +namespace ProbabilityTheory + +variable {α β : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} {κ : Kernel α β} + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {f : β → E} {a : α} + +namespace Kernel + +lemma IsFiniteKernel.integrable (μ : Measure α) [IsFiniteMeasure μ] + (κ : Kernel α β) [IsFiniteKernel κ] {s : Set β} (hs : MeasurableSet s) : + Integrable (fun x ↦ (κ x s).toReal) μ := by + refine Integrable.mono' (integrable_const (IsFiniteKernel.bound κ).toReal) + ((κ.measurable_coe hs).ennreal_toReal.aestronglyMeasurable) + (ae_of_all μ fun x ↦ ?_) + rw [Real.norm_eq_abs, abs_of_nonneg ENNReal.toReal_nonneg, + ENNReal.toReal_le_toReal (measure_ne_top _ _) (IsFiniteKernel.bound_ne_top _)] + exact Kernel.measure_le_bound _ _ _ + +lemma IsMarkovKernel.integrable (μ : Measure α) [IsFiniteMeasure μ] + (κ : Kernel α β) [IsMarkovKernel κ] {s : Set β} (hs : MeasurableSet s) : + Integrable (fun x => (κ x s).toReal) μ := + IsFiniteKernel.integrable μ κ hs + +lemma integral_congr_ae₂ {f g : α → β → E} {μ : Measure α} (h : ∀ᵐ a ∂μ, f a =ᵐ[κ a] g a) : + ∫ a, ∫ b, f a b ∂(κ a) ∂μ = ∫ a, ∫ b, g a b ∂(κ a) ∂μ := by + apply integral_congr_ae + filter_upwards [h] with _ ha + apply integral_congr_ae + filter_upwards [ha] with _ hb using hb + +section Deterministic + +variable [CompleteSpace E] {g : α → β} + +theorem integral_deterministic' (hg : Measurable g) (hf : StronglyMeasurable f) : + ∫ x, f x ∂deterministic g hg a = f (g a) := by + rw [deterministic_apply, integral_dirac' _ _ hf] + +@[simp] +theorem integral_deterministic [MeasurableSingletonClass β] (hg : Measurable g) : + ∫ x, f x ∂deterministic g hg a = f (g a) := by + rw [deterministic_apply, integral_dirac _ (g a)] + +theorem setIntegral_deterministic' (hg : Measurable g) + (hf : StronglyMeasurable f) {s : Set β} (hs : MeasurableSet s) [Decidable (g a ∈ s)] : + ∫ x in s, f x ∂deterministic g hg a = if g a ∈ s then f (g a) else 0 := by + rw [deterministic_apply, setIntegral_dirac' hf _ hs] + +@[deprecated (since := "2024-04-17")] +alias set_integral_deterministic' := setIntegral_deterministic' + +@[simp] +theorem setIntegral_deterministic [MeasurableSingletonClass β] (hg : Measurable g) + (s : Set β) [Decidable (g a ∈ s)] : + ∫ x in s, f x ∂deterministic g hg a = if g a ∈ s then f (g a) else 0 := by + rw [deterministic_apply, setIntegral_dirac f _ s] + +@[deprecated (since := "2024-04-17")] +alias set_integral_deterministic := setIntegral_deterministic + +end Deterministic + +section Const + +@[simp] +theorem integral_const {μ : Measure β} : ∫ x, f x ∂const α μ a = ∫ x, f x ∂μ := by + rw [const_apply] + +@[simp] +theorem setIntegral_const {μ : Measure β} {s : Set β} : + ∫ x in s, f x ∂const α μ a = ∫ x in s, f x ∂μ := by rw [const_apply] + +@[deprecated (since := "2024-04-17")] +alias set_integral_const := setIntegral_const + +end Const + +section Restrict + +variable {s t : Set β} + +@[simp] +theorem integral_restrict (hs : MeasurableSet s) : + ∫ x, f x ∂κ.restrict hs a = ∫ x in s, f x ∂κ a := by + rw [restrict_apply] + +@[simp] +theorem setIntegral_restrict (hs : MeasurableSet s) (t : Set β) : + ∫ x in t, f x ∂κ.restrict hs a = ∫ x in t ∩ s, f x ∂κ a := by + rw [restrict_apply, Measure.restrict_restrict' hs] + +@[deprecated (since := "2024-04-17")] +alias set_integral_restrict := setIntegral_restrict + +end Restrict + +section Piecewise + +variable {η : Kernel α β} {s : Set α} {hs : MeasurableSet s} [DecidablePred (· ∈ s)] + +theorem integral_piecewise (a : α) (g : β → E) : + ∫ b, g b ∂piecewise hs κ η a = if a ∈ s then ∫ b, g b ∂κ a else ∫ b, g b ∂η a := by + simp_rw [piecewise_apply]; split_ifs <;> rfl + +theorem setIntegral_piecewise (a : α) (g : β → E) (t : Set β) : + ∫ b in t, g b ∂piecewise hs κ η a = + if a ∈ s then ∫ b in t, g b ∂κ a else ∫ b in t, g b ∂η a := by + simp_rw [piecewise_apply]; split_ifs <;> rfl + +@[deprecated (since := "2024-04-17")] +alias set_integral_piecewise := setIntegral_piecewise + +end Piecewise + +end Kernel +end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/MeasurableIntegral.lean b/Mathlib/Probability/Kernel/MeasurableIntegral.lean index 9d5915b707937..dc0acc26cac82 100644 --- a/Mathlib/Probability/Kernel/MeasurableIntegral.lean +++ b/Mathlib/Probability/Kernel/MeasurableIntegral.lean @@ -3,9 +3,8 @@ Copyright (c) 2023 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ -import Mathlib.Probability.Kernel.Basic -import Mathlib.MeasureTheory.Constructions.Prod.Basic import Mathlib.MeasureTheory.Integral.DominatedConvergence +import Mathlib.Probability.Kernel.Basic /-! # Measurability of the integral against a kernel diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index 95e1a9132d2a8..4b097fac62731 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Probability.IdentDistrib +import Mathlib.Probability.Independence.Integrable import Mathlib.MeasureTheory.Integral.DominatedConvergence import Mathlib.Analysis.SpecificLimits.FloorPow import Mathlib.Analysis.PSeries From 7d7d3bfab3fa429283c7c7f16c80f76bff237522 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Thu, 19 Sep 2024 18:37:51 +0000 Subject: [PATCH 055/170] feat(Topology/AlexandrovDiscrete): generalize some lemmas (#16932) - add `mem_exterior_iff_specializes`; - prove `IsCompact.exterior_iff`; - drop `[AlexandrovDiscrete _]` assumption in some lemmas. --- Mathlib/Topology/AlexandrovDiscrete.lean | 101 ++++++++++++++--------- 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/Mathlib/Topology/AlexandrovDiscrete.lean b/Mathlib/Topology/AlexandrovDiscrete.lean index a754e4fc9b10d..2c3353a35125b 100644 --- a/Mathlib/Topology/AlexandrovDiscrete.lean +++ b/Mathlib/Topology/AlexandrovDiscrete.lean @@ -5,6 +5,7 @@ Authors: Yaël Dillies -/ import Mathlib.Data.Set.Image import Mathlib.Topology.Bases +import Mathlib.Tactic.Peel import Mathlib.Topology.Inseparable import Mathlib.Topology.Compactness.Compact @@ -127,6 +128,10 @@ def exterior (s : Set α) : Set α := (𝓝ˢ s).ker lemma exterior_singleton_eq_ker_nhds (a : α) : exterior {a} = (𝓝 a).ker := by simp [exterior] +@[simp] +theorem mem_exterior_singleton : x ∈ exterior {y} ↔ x ⤳ y := by + rw [exterior_singleton_eq_ker_nhds, ker_nhds_eq_specializes, mem_setOf] + lemma exterior_def (s : Set α) : exterior s = ⋂₀ {t : Set α | IsOpen t ∧ s ⊆ t} := (hasBasis_nhdsSet _).ker.trans sInter_eq_biInter.symm @@ -143,18 +148,60 @@ lemma exterior_minimal (h₁ : s ⊆ t) (h₂ : IsOpen t) : exterior s ⊆ t := lemma IsOpen.exterior_eq (h : IsOpen s) : exterior s = s := (exterior_minimal Subset.rfl h).antisymm subset_exterior -lemma IsOpen.exterior_subset_iff (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t := +lemma IsOpen.exterior_subset (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t := ⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩ +@[deprecated (since := "2024-09-18")] alias IsOpen.exterior_subset_iff := IsOpen.exterior_subset + +@[simp] +theorem exterior_iUnion {ι : Sort*} (s : ι → Set α) : + exterior (⋃ i, s i) = ⋃ i, exterior (s i) := by + simp only [exterior, nhdsSet_iUnion, ker_iSup] + +@[simp] +theorem exterior_union (s t : Set α) : exterior (s ∪ t) = exterior s ∪ exterior t := by + simp only [exterior, nhdsSet_union, ker_sup] + +@[simp] +theorem exterior_sUnion (S : Set (Set α)) : exterior (⋃₀ S) = ⋃ s ∈ S, exterior s := by + simp only [sUnion_eq_biUnion, exterior_iUnion] + +theorem mem_exterior_iff_specializes : a ∈ exterior s ↔ ∃ b ∈ s, a ⤳ b := calc + a ∈ exterior s ↔ a ∈ exterior (⋃ x ∈ s, {x}) := by simp + _ ↔ ∃ b ∈ s, a ⤳ b := by + simp only [exterior_iUnion, mem_exterior_singleton, mem_iUnion₂, exists_prop] + @[mono] lemma exterior_mono : Monotone (exterior : Set α → Set α) := fun _s _t h ↦ ker_mono <| nhdsSet_mono h +/-- This name was used to be used for the `Iff` version, +see `exterior_subset_exterior_iff_nhdsSet`. +-/ +@[gcongr] lemma exterior_subset_exterior (h : s ⊆ t) : exterior s ⊆ exterior t := exterior_mono h + +@[simp] lemma exterior_subset_exterior_iff_nhdsSet : exterior s ⊆ exterior t ↔ 𝓝ˢ s ≤ 𝓝ˢ t := by + simp (config := {contextual := true}) only [subset_exterior_iff, (hasBasis_nhdsSet _).ge_iff, + and_imp, IsOpen.mem_nhdsSet, IsOpen.exterior_subset] + +theorem exterior_eq_exterior_iff_nhdsSet : exterior s = exterior t ↔ 𝓝ˢ s = 𝓝ˢ t := by + simp [le_antisymm_iff] + +lemma specializes_iff_exterior_subset : x ⤳ y ↔ exterior {x} ⊆ exterior {y} := by + simp [Specializes] + @[simp] lemma exterior_empty : exterior (∅ : Set α) = ∅ := isOpen_empty.exterior_eq @[simp] lemma exterior_univ : exterior (univ : Set α) = univ := isOpen_univ.exterior_eq @[simp] lemma exterior_eq_empty : exterior s = ∅ ↔ s = ∅ := ⟨eq_bot_mono subset_exterior, by rintro rfl; exact exterior_empty⟩ +@[simp] lemma nhdsSet_exterior (s : Set α) : 𝓝ˢ (exterior s) = 𝓝ˢ s := by + refine le_antisymm ((hasBasis_nhdsSet _).ge_iff.2 ?_) (nhdsSet_mono subset_exterior) + exact fun U ⟨hUo, hsU⟩ ↦ hUo.mem_nhdsSet.2 <| hUo.exterior_subset.2 hsU + +@[simp] lemma exterior_exterior (s : Set α) : exterior (exterior s) = exterior s := by + simp only [exterior_eq_exterior_iff_nhdsSet, nhdsSet_exterior] + lemma Inducing.alexandrovDiscrete [AlexandrovDiscrete α] {f : β → α} (h : Inducing f) : AlexandrovDiscrete β where isOpen_sInter S hS := by @@ -163,20 +210,18 @@ lemma Inducing.alexandrovDiscrete [AlexandrovDiscrete α] {f : β → α} (h : I refine ⟨_, isOpen_iInter₂ hU, ?_⟩ simp_rw [preimage_iInter, htU, sInter_eq_biInter] -lemma IsOpen.exterior_subset (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t := - ⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩ +theorem IsCompact.exterior_iff : IsCompact (exterior s) ↔ IsCompact s := by + simp only [isCompact_iff_finite_subcover] + peel with ι U hUo + simp only [(isOpen_iUnion hUo).exterior_subset, + (isOpen_iUnion fun i ↦ isOpen_iUnion fun _ ↦ hUo i).exterior_subset] + +protected alias ⟨IsCompact.of_exterior, IsCompact.exterior⟩ := IsCompact.exterior_iff + +@[deprecated IsCompact.exterior (since := "2024-09-18")] +lemma Set.Finite.isCompact_exterior (hs : s.Finite) : IsCompact (exterior s) := + hs.isCompact.exterior -lemma Set.Finite.isCompact_exterior (hs : s.Finite) : IsCompact (exterior s) := by - classical - refine isCompact_of_finite_subcover fun f hf hsf ↦ ?_ - choose g hg using fun a (ha : a ∈ exterior s) ↦ mem_iUnion.1 (hsf ha) - refine ⟨hs.toFinset.attach.image fun a ↦ - g a.1 <| subset_exterior <| (Finite.mem_toFinset _).1 a.2, - (isOpen_iUnion fun i ↦ isOpen_iUnion ?_).exterior_subset.2 ?_⟩ - · exact fun _ ↦ hf _ - refine fun a ha ↦ mem_iUnion₂.2 ⟨_, ?_, hg _ <| subset_exterior ha⟩ - simp only [Finset.mem_image, Finset.mem_attach, true_and, Subtype.exists, Finite.mem_toFinset] - exact ⟨a, ha, rfl⟩ end lemma AlexandrovDiscrete.sup {t₁ t₂ : TopologicalSpace α} (_ : @AlexandrovDiscrete α t₁) @@ -220,47 +265,25 @@ lemma exterior_singleton_subset_iff_mem_nhds : exterior {a} ⊆ t ↔ t ∈ 𝓝 lemma gc_exterior_interior : GaloisConnection (exterior : Set α → Set α) interior := fun s t ↦ by simp [exterior_subset_iff, subset_interior_iff] -@[simp] lemma exterior_exterior (s : Set α) : exterior (exterior s) = exterior s := - isOpen_exterior.exterior_eq - -@[simp] lemma exterior_union (s t : Set α) : exterior (s ∪ t) = exterior s ∪ exterior t := - gc_exterior_interior.l_sup - -@[simp] lemma nhdsSet_exterior (s : Set α) : 𝓝ˢ (exterior s) = 𝓝ˢ s := by - ext t; simp_rw [← exterior_subset_iff_mem_nhdsSet, exterior_exterior] - @[simp] lemma principal_exterior (s : Set α) : 𝓟 (exterior s) = 𝓝ˢ s := by rw [← nhdsSet_exterior, isOpen_exterior.nhdsSet_eq] -@[simp] lemma exterior_subset_exterior : exterior s ⊆ exterior t ↔ 𝓝ˢ s ≤ 𝓝ˢ t := by - refine ⟨?_, fun h ↦ ker_mono h⟩ - simp_rw [le_def, ← exterior_subset_iff_mem_nhdsSet] - exact fun h u ↦ h.trans - -lemma specializes_iff_exterior_subset : x ⤳ y ↔ exterior {x} ⊆ exterior {y} := by - simp [Specializes] - lemma isOpen_iff_forall_specializes : IsOpen s ↔ ∀ x y, x ⤳ y → y ∈ s → x ∈ s := by - refine ⟨fun hs x y hxy ↦ hxy.mem_open hs, fun hs ↦ ?_⟩ - simp_rw [specializes_iff_exterior_subset] at hs - simp_rw [isOpen_iff_mem_nhds, mem_nhds_iff] - rintro a ha - refine ⟨_, fun b hb ↦ hs _ _ ?_ ha, isOpen_exterior, subset_exterior <| mem_singleton _⟩ - rwa [isOpen_exterior.exterior_subset, singleton_subset_iff] + simp only [← exterior_subset_iff_isOpen, Set.subset_def, mem_exterior_iff_specializes, exists_imp, + and_imp, @forall_swap (_ ⤳ _)] lemma alexandrovDiscrete_coinduced {β : Type*} {f : α → β} : @AlexandrovDiscrete β (coinduced f ‹_›) := @AlexandrovDiscrete.mk β (coinduced f ‹_›) fun S hS ↦ by rw [isOpen_coinduced, preimage_sInter]; exact isOpen_iInter₂ hS - instance AlexandrovDiscrete.toFirstCountable : FirstCountableTopology α where nhds_generated_countable a := ⟨{exterior {a}}, countable_singleton _, by simp⟩ instance AlexandrovDiscrete.toLocallyCompactSpace : LocallyCompactSpace α where local_compact_nhds a _U hU := ⟨exterior {a}, isOpen_exterior.mem_nhds <| subset_exterior <| mem_singleton _, - exterior_singleton_subset_iff_mem_nhds.2 hU, (finite_singleton _).isCompact_exterior⟩ + exterior_singleton_subset_iff_mem_nhds.2 hU, (finite_singleton _).isCompact.exterior⟩ instance Subtype.instAlexandrovDiscrete {p : α → Prop} : AlexandrovDiscrete {a // p a} := inducing_subtype_val.alexandrovDiscrete From 025dd76af3eac349f2101f7b613f3b3a18655795 Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Thu, 19 Sep 2024 18:58:35 +0000 Subject: [PATCH 056/170] feat(NumberTheory/LSeries): completed L-functions (#16894) Define the completed L-function for a function on `ZMod N`, and prove its functional equation. --- Mathlib/NumberTheory/LSeries/ZMod.lean | 300 ++++++++++++++++++++++++- 1 file changed, 299 insertions(+), 1 deletion(-) diff --git a/Mathlib/NumberTheory/LSeries/ZMod.lean b/Mathlib/NumberTheory/LSeries/ZMod.lean index c8ae61d647c1c..66dbde51f1f55 100644 --- a/Mathlib/NumberTheory/LSeries/ZMod.lean +++ b/Mathlib/NumberTheory/LSeries/ZMod.lean @@ -12,7 +12,10 @@ import Mathlib.NumberTheory.LSeries.RiemannZeta # L-series of functions on `ZMod N` We show that if `N` is a positive integer and `Φ : ZMod N → ℂ`, then the L-series of `Φ` has -analytic continuation (away from a pole at `s = 1` if `∑ j, Φ j ≠ 0`). +analytic continuation (away from a pole at `s = 1` if `∑ j, Φ j ≠ 0`) and satisfies a functional +equation. We also define completed L-functions (given by multiplying the naive L-function by a +Gamma-factor), and prove analytic continuation and functional equations for these too, assuming `Φ` +is either even or odd. The most familiar case is when `Φ` is a Dirichlet character, but the results here are valid for general functions; for the specific case of Dirichlet characters see @@ -21,15 +24,35 @@ for general functions; for the specific case of Dirichlet characters see ## Main definitions * `ZMod.LFunction Φ s`: the meromorphic continuation of the function `∑ n : ℕ, Φ n * n ^ (-s)`. +* `ZMod.completedLFunction Φ s`: the completed L-function, which for *almost* all `s` is equal to + `LFunction Φ s` multiplied by an Archimedean Gamma-factor. + +Note that `ZMod.completedLFunction Φ s` is only mathematically well-defined if `Φ` is either even +or odd. Here we extend it to all functions `Φ` by linearity (but the functional equation only holds +if `Φ` is either even or odd). ## Main theorems +Results for non-completed L-functions: + * `ZMod.LFunction_eq_LSeries`: if `1 < re s` then the `LFunction` coincides with the naive `LSeries`. * `ZMod.differentiableAt_LFunction`: `ZMod.LFunction Φ` is differentiable at `s ∈ ℂ` if either `s ≠ 1` or `∑ j, Φ j = 0`. * `ZMod.LFunction_one_sub`: the functional equation relating `LFunction Φ (1 - s)` to `LFunction (𝓕 Φ) s`, where `𝓕` is the Fourier transform. + +Results for completed L-functions: + +* `ZMod.LFunction_eq_completed_div_gammaFactor_even` and + `LFunction_eq_completed_div_gammaFactor_odd`: we have + `LFunction Φ s = completedLFunction Φ s / Gammaℝ s` for `Φ` even, and + `LFunction Φ s = completedLFunction Φ s / Gammaℝ (s + 1)` for `Φ` odd. (We formulate it this way + around so it is still valid at the poles of the Gamma factor.) +* `ZMod.differentiableAt_completedLFunction`: `ZMod.completedLFunction Φ` is differentiable at + `s ∈ ℂ`, unless `s = 1` and `∑ j, Φ j ≠ 0`, or `s = 0` and `Φ 0 ≠ 0`. +* `ZMod.completedLFunction_one_sub_even` and `ZMod.completedLFunction_one_sub_odd`: + the functional equation relating `completedLFunction Φ (1 - s)` to `completedLFunction (𝓕 Φ) s`. -/ open HurwitzZeta Complex ZMod Finset Classical Topology Filter Set @@ -219,4 +242,279 @@ theorem LFunction_one_sub (Φ : ZMod N → ℂ) {s : ℂ} simp_rw [neg_neg, mul_sum, ← sum_add_distrib, ← mul_assoc, mul_comm _ (Φ _), mul_assoc, ← mul_add, map_neg, add_comm] +section signed + +variable {Φ : ZMod N → ℂ} + +lemma LFunction_def_even (hΦ : Φ.Even) (s : ℂ) : + LFunction Φ s = N ^ (-s) * ∑ j : ZMod N, Φ j * hurwitzZetaEven (toAddCircle j) s := by + simp only [LFunction, hurwitzZeta, mul_add (Φ _), sum_add_distrib] + congr 1 + simp only [add_right_eq_self, ← neg_eq_self ℂ, ← sum_neg_distrib] + refine Fintype.sum_equiv (.neg _) _ _ fun i ↦ ?_ + simp only [Equiv.neg_apply, hΦ i, map_neg, hurwitzZetaOdd_neg, mul_neg] + +lemma LFunction_def_odd (hΦ : Φ.Odd) (s : ℂ) : + LFunction Φ s = N ^ (-s) * ∑ j : ZMod N, Φ j * hurwitzZetaOdd (toAddCircle j) s := by + simp only [LFunction, hurwitzZeta, mul_add (Φ _), sum_add_distrib] + congr 1 + simp only [add_left_eq_self, ← neg_eq_self ℂ, ← sum_neg_distrib] + refine Fintype.sum_equiv (.neg _) _ _ fun i ↦ ?_ + simp only [Equiv.neg_apply, hΦ i, map_neg, hurwitzZetaEven_neg, neg_mul] + +/-- Explicit formula for `LFunction Φ 0` when `Φ` is even. -/ +@[simp] lemma LFunction_apply_zero_of_even (hΦ : Φ.Even) : + LFunction Φ 0 = -Φ 0 / 2 := by + simp only [LFunction_def_even hΦ, neg_zero, cpow_zero, hurwitzZetaEven_apply_zero, + toAddCircle_eq_zero, mul_ite, mul_div, mul_neg_one, mul_zero, sum_ite_eq', Finset.mem_univ, + ↓reduceIte, one_mul] + +/-- The L-function of an even function vanishes at negative even integers. -/ +@[simp] lemma LFunction_neg_two_mul_nat_add_one (hΦ : Φ.Even) (n : ℕ) : + LFunction Φ (-(2 * (n + 1))) = 0 := by + simp only [LFunction_def_even hΦ, hurwitzZetaEven_neg_two_mul_nat_add_one, mul_zero, + sum_const_zero, ← neg_mul] + +/-- The L-function of an odd function vanishes at negative odd integers. -/ +@[simp] lemma LFunction_neg_two_mul_nat_sub_one (hΦ : Φ.Odd) (n : ℕ) : + LFunction Φ (-(2 * n) - 1) = 0 := by + simp only [LFunction_def_odd hΦ, hurwitzZetaOdd_neg_two_mul_nat_sub_one, mul_zero, ← neg_mul, + sum_const_zero] + +/-- +The completed L-function of a function `Φ : ZMod N → ℂ`. + +This is only mathematically meaningful if `Φ` is either even, or odd; here we extend this to all `Φ` +by linearity. +-/ +noncomputable def completedLFunction (Φ : ZMod N → ℂ) (s : ℂ) : ℂ := + N ^ (-s) * ∑ j, Φ j * completedHurwitzZetaEven (toAddCircle j) s + + N ^ (-s) * ∑ j, Φ j * completedHurwitzZetaOdd (toAddCircle j) s + +@[simp] lemma completedLFunction_zero (s : ℂ) : completedLFunction (0 : ZMod N → ℂ) s = 0 := by + simp only [completedLFunction, Pi.zero_apply, zero_mul, sum_const_zero, mul_zero, zero_add] + +lemma completedLFunction_def_even (hΦ : Φ.Even) (s : ℂ) : + completedLFunction Φ s = N ^ (-s) * ∑ j, Φ j * completedHurwitzZetaEven (toAddCircle j) s := by + suffices ∑ j, Φ j * completedHurwitzZetaOdd (toAddCircle j) s = 0 by + rw [completedLFunction, this, mul_zero, add_zero] + refine (hΦ.mul_odd fun j ↦ ?_).sum_eq_zero + rw [map_neg, completedHurwitzZetaOdd_neg] + +lemma completedLFunction_def_odd (hΦ : Φ.Odd) (s : ℂ) : + completedLFunction Φ s = N ^ (-s) * ∑ j, Φ j * completedHurwitzZetaOdd (toAddCircle j) s := by + suffices ∑ j, Φ j * completedHurwitzZetaEven (toAddCircle j) s = 0 by + rw [completedLFunction, this, mul_zero, zero_add] + refine (hΦ.mul_even fun j ↦ ?_).sum_eq_zero + rw [map_neg, completedHurwitzZetaEven_neg] + +/-- +The completed L-function of a function `ZMod 1 → ℂ` is a scalar multiple of the completed Riemann +zeta function. +-/ +lemma completedLFunction_modOne_eq (Φ : ZMod 1 → ℂ) (s : ℂ) : + completedLFunction Φ s = Φ 1 * completedRiemannZeta s := by + rw [completedLFunction_def_even (show Φ.Even from fun _ ↦ congr_arg Φ (Subsingleton.elim ..)), + Nat.cast_one, one_cpow, one_mul, ← singleton_eq_univ 0, sum_singleton, map_zero, + completedHurwitzZetaEven_zero, Subsingleton.elim 0 1] + +/-- +The completed L-function of a function `ZMod N → ℂ`, modified by adding multiples of `N ^ (-s) / s` +and `N ^ (-s) / (1 - s)` to make it entire. +-/ +noncomputable def completedLFunction₀ (Φ : ZMod N → ℂ) (s : ℂ) : ℂ := + N ^ (-s) * ∑ j : ZMod N, Φ j * completedHurwitzZetaEven₀ (toAddCircle j) s + + N ^ (-s) * ∑ j : ZMod N, Φ j * completedHurwitzZetaOdd (toAddCircle j) s + +/-- The function `completedLFunction₀ Φ` is differentiable. -/ +lemma differentiable_completedLFunction₀ (Φ : ZMod N → ℂ) : + Differentiable ℂ (completedLFunction₀ Φ) := by + refine .add ?_ ?_ <;> + refine (differentiable_neg.const_cpow <| .inl <| NeZero.ne _).mul (.sum fun i _ ↦ .const_mul ?_ _) + exacts [differentiable_completedHurwitzZetaEven₀ _, differentiable_completedHurwitzZetaOdd _] + +lemma completedLFunction_eq (Φ : ZMod N → ℂ) (s : ℂ) : + completedLFunction Φ s = + completedLFunction₀ Φ s - N ^ (-s) * Φ 0 / s - N ^ (-s) * (∑ j, Φ j) / (1 - s) := by + simp only [completedLFunction, completedHurwitzZetaEven_eq, toAddCircle_eq_zero, div_eq_mul_inv, + ite_mul, one_mul, zero_mul, mul_sub, mul_ite, mul_zero, sum_sub_distrib, Fintype.sum_ite_eq', + ← sum_mul, completedLFunction₀, mul_assoc] + abel + +/-- +The completed L-function of a function `ZMod N → ℂ` is differentiable, with the following +exceptions: at `s = 1` if `∑ j, Φ j ≠ 0`; and at `s = 0` if `Φ 0 ≠ 0`. +-/ +lemma differentiableAt_completedLFunction (Φ : ZMod N → ℂ) (s : ℂ) (hs₀ : s ≠ 0 ∨ Φ 0 = 0) + (hs₁ : s ≠ 1 ∨ ∑ j, Φ j = 0) : DifferentiableAt ℂ (completedLFunction Φ) s := by + simp only [funext (completedLFunction_eq Φ), mul_div_assoc] + -- We know `completedLFunction₀` is differentiable everywhere, so it suffices to show that the + -- correction terms from `completedLFunction_eq` are differentiable at `s`. + refine ((differentiable_completedLFunction₀ _ _).sub ?_).sub ?_ + · -- term with `1 / s` + refine ((differentiable_neg.const_cpow <| .inl <| NeZero.ne _) s).mul (hs₀.elim ?_ ?_) + · exact fun h ↦ (differentiableAt_const _).div differentiableAt_id h + · exact fun h ↦ by simp only [h, funext zero_div, differentiableAt_const] + · -- term with `1 / (1 - s)` + refine ((differentiable_neg.const_cpow <| .inl <| NeZero.ne _) s).mul (hs₁.elim ?_ ?_) + · exact fun h ↦ (differentiableAt_const _).div (by fun_prop) (by rwa [sub_ne_zero, ne_comm]) + · exact fun h ↦ by simp only [h, zero_div, differentiableAt_const] + +/-- +Special case of `differentiableAt_completedLFunction` asserting differentiability everywhere +under suitable hypotheses. +-/ +lemma differentiable_completedLFunction (hΦ₂ : Φ 0 = 0) (hΦ₃ : ∑ j, Φ j = 0) : + Differentiable ℂ (completedLFunction Φ) := + fun s ↦ differentiableAt_completedLFunction Φ s (.inr hΦ₂) (.inr hΦ₃) + +/-- +Relation between the completed L-function and the usual one (even case). +We state it this way around so it holds at the poles of the gamma factor as well +(except at `s = 0`, where it is genuinely false if `N > 1` and `Φ 0 ≠ 0`). +-/ +lemma LFunction_eq_completed_div_gammaFactor_even (hΦ : Φ.Even) (s : ℂ) (hs : s ≠ 0 ∨ Φ 0 = 0) : + LFunction Φ s = completedLFunction Φ s / Gammaℝ s := by + simp only [completedLFunction_def_even hΦ, LFunction_def_even hΦ, mul_div_assoc, sum_div] + congr 2 with i + rcases ne_or_eq i 0 with hi | rfl + · rw [hurwitzZetaEven_def_of_ne_or_ne (.inl (hi ∘ toAddCircle_eq_zero.mp))] + · rcases hs with hs | hΦ' + · rw [hurwitzZetaEven_def_of_ne_or_ne (.inr hs)] + · simp only [hΦ', map_zero, zero_mul] + +/-- +Relation between the completed L-function and the usual one (odd case). +We state it this way around so it holds at the poles of the gamma factor as well. +-/ +lemma LFunction_eq_completed_div_gammaFactor_odd (hΦ : Φ.Odd) (s : ℂ) : + LFunction Φ s = completedLFunction Φ s / Gammaℝ (s + 1) := by + simp only [LFunction_def_odd hΦ, completedLFunction_def_odd hΦ, hurwitzZetaOdd, mul_div_assoc, + sum_div] + +/-- +First form of functional equation for completed L-functions (even case). + +Private because it is superseded by `completedLFunction_one_sub_even` below, which is valid for a +much wider range of `s`. +-/ +private lemma completedLFunction_one_sub_of_one_lt_even (hΦ : Φ.Even) {s : ℂ} (hs : 1 < re s) : + completedLFunction Φ (1 - s) = N ^ (s - 1) * completedLFunction (𝓕 Φ) s := by + have hs₀ : s ≠ 0 := ne_zero_of_one_lt_re hs + have hs₁ : s ≠ 1 := (lt_irrefl _ <| one_re ▸ · ▸ hs) + -- strip down to the key equality: + suffices ∑ x, Φ x * completedCosZeta (toAddCircle x) s = completedLFunction (𝓕 Φ) s by + simp only [completedLFunction_def_even hΦ, neg_sub, completedHurwitzZetaEven_one_sub, this] + -- reduce to equality with un-completed L-functions: + suffices ∑ x, Φ x * cosZeta (toAddCircle x) s = LFunction (𝓕 Φ) s by + simpa only [cosZeta, Function.update_noteq hs₀, ← mul_div_assoc, ← sum_div, + LFunction_eq_completed_div_gammaFactor_even (dft_even_iff.mpr hΦ) _ (.inl hs₀), + div_left_inj' (Gammaℝ_ne_zero_of_re_pos (zero_lt_one.trans hs))] + -- expand out `LFunction (𝓕 Φ)` and use parity: + simp only [cosZeta_eq, ← mul_div_assoc _ _ (2 : ℂ), mul_add, ← sum_div, sum_add_distrib, + LFunction_dft Φ (.inr hs₁), map_neg, div_eq_iff (two_ne_zero' ℂ), mul_two, add_left_inj] + exact Fintype.sum_equiv (.neg _) _ _ (by simp [hΦ _]) + +/-- +First form of functional equation for completed L-functions (odd case). + +Private because it is superseded by `completedLFunction_one_sub_odd` below, which is valid for a +much wider range of `s`. +-/ +private lemma completedLFunction_one_sub_of_one_lt_odd (hΦ : Φ.Odd) {s : ℂ} (hs : 1 < re s) : + completedLFunction Φ (1 - s) = N ^ (s - 1) * I * completedLFunction (𝓕 Φ) s := by + -- strip down to the key equality: + suffices ∑ x, Φ x * completedSinZeta (toAddCircle x) s = I * completedLFunction (𝓕 Φ) s by + simp only [completedLFunction_def_odd hΦ, neg_sub, completedHurwitzZetaOdd_one_sub, this, + mul_assoc] + -- reduce to equality with un-completed L-functions: + suffices ∑ x, Φ x * sinZeta (toAddCircle x) s = I * LFunction (𝓕 Φ) s by + have hs' : 0 < re (s + 1) := by simp only [add_re, one_re]; linarith + simpa only [sinZeta, ← mul_div_assoc, ← sum_div, div_left_inj' (Gammaℝ_ne_zero_of_re_pos hs'), + LFunction_eq_completed_div_gammaFactor_odd (dft_odd_iff.mpr hΦ)] + -- now calculate: + calc ∑ x, Φ x * sinZeta (toAddCircle x) s + _ = (∑ x, Φ x * expZeta (toAddCircle x) s) / (2 * I) + - (∑ x, Φ x * expZeta (toAddCircle (-x)) s) / (2 * I) := by + simp only [sinZeta_eq, ← mul_div_assoc, mul_sub, sub_div, sum_sub_distrib, sum_div, map_neg] + _ = (∑ x, Φ (-x) * expZeta (toAddCircle (-x)) s) / (_) - (_) := by + congrm ?_ / _ - _ + exact (Fintype.sum_equiv (.neg _) _ _ fun x ↦ by rfl).symm + _ = -I⁻¹ * LFunction (𝓕 Φ) s := by + simp only [hΦ _, neg_mul, sum_neg_distrib, LFunction_dft Φ (.inl hΦ.map_zero)] + ring + _ = I * LFunction (𝓕 Φ) s := by rw [inv_I, neg_neg] + +/-- +Functional equation for completed L-functions (even case), valid at all points of differentiability. +-/ +theorem completedLFunction_one_sub_even (hΦ : Φ.Even) (s : ℂ) + (hs₀ : s ≠ 0 ∨ ∑ j, Φ j = 0) (hs₁ : s ≠ 1 ∨ Φ 0 = 0) : + completedLFunction Φ (1 - s) = N ^ (s - 1) * completedLFunction (𝓕 Φ) s := by + -- We prove this using `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`, so we need to + -- gather up the ingredients for this big theorem. + -- First set up some notations: + let F (t) := completedLFunction Φ (1 - t) + let G (t) := ↑N ^ (t - 1) * completedLFunction (𝓕 Φ) t + -- Set on which F, G are analytic: + let U := {t : ℂ | (t ≠ 0 ∨ ∑ j, Φ j = 0) ∧ (t ≠ 1 ∨ Φ 0 = 0)} + -- Properties of U: + have hsU : s ∈ U := ⟨hs₀, hs₁⟩ + have h2U : 2 ∈ U := ⟨.inl two_ne_zero, .inl (OfNat.ofNat_ne_one _)⟩ + have hUo : IsOpen U := (isOpen_compl_singleton.union isOpen_const).inter + (isOpen_compl_singleton.union isOpen_const) + have hUp : IsPreconnected U := by + -- need to write `U` as the complement of an obviously countable set + let Uc : Set ℂ := (if ∑ j, Φ j = 0 then ∅ else {0}) ∪ (if Φ 0 = 0 then ∅ else {1}) + have : Uc.Countable := by + apply Countable.union <;> + split_ifs <;> + simp only [countable_singleton, countable_empty] + convert (this.isConnected_compl_of_one_lt_rank ?_).isPreconnected using 1 + · ext x + by_cases h : Φ 0 = 0 <;> + by_cases h' : ∑ j, Φ j = 0 <;> + simp [U, Uc, h, h', and_comm] + · simp only [rank_real_complex, Nat.one_lt_ofNat] + -- Analyticity on U: + have hF : AnalyticOn ℂ F U := by + refine DifferentiableOn.analyticOn (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo + refine (differentiableAt_completedLFunction Φ _ ?_ ?_).comp t (differentiableAt_id.const_sub 1) + exacts [ht.2.imp_left (sub_ne_zero.mpr ∘ Ne.symm), ht.1.imp_left sub_eq_self.not.mpr] + have hG : AnalyticOn ℂ G U := by + refine DifferentiableOn.analyticOn (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo + apply ((differentiableAt_id.sub_const 1).const_cpow (.inl (NeZero.ne _))).mul + apply differentiableAt_completedLFunction _ _ (ht.1.imp_right fun h ↦ dft_apply_zero Φ ▸ h) + exact ht.2.imp_right (fun h ↦ by simp only [← dft_apply_zero, dft_dft, neg_zero, h, smul_zero]) + -- set where we know equality + have hV : {z | 1 < re z} ∈ 𝓝 2 := (continuous_re.isOpen_preimage _ isOpen_Ioi).mem_nhds (by simp) + have hFG : F =ᶠ[𝓝 2] G := eventually_of_mem hV <| fun t ht ↦ by + simpa only [F, G, pow_zero, mul_one] using completedLFunction_one_sub_of_one_lt_even hΦ ht + -- now apply the big hammer to finish + exact hF.eqOn_of_preconnected_of_eventuallyEq hG hUp h2U hFG hsU + +/-- Functional equation for completed L-functions (odd case), valid for all `s`. -/ +theorem completedLFunction_one_sub_odd (hΦ : Φ.Odd) (s : ℂ) : + completedLFunction Φ (1 - s) = N ^ (s - 1) * I * completedLFunction (𝓕 Φ) s := by + -- This is much easier than the even case since both functions are entire. + -- First set up some notations: + let F (t) := completedLFunction Φ (1 - t) + let G (t) := ↑N ^ (t - 1) * I * completedLFunction (𝓕 Φ) t + -- check F, G globally differentiable + have hF : Differentiable ℂ F := (differentiable_completedLFunction hΦ.map_zero + hΦ.sum_eq_zero).comp (differentiable_id.const_sub 1) + have hG : Differentiable ℂ G := by + apply (((differentiable_id.sub_const 1).const_cpow (.inl (NeZero.ne _))).mul_const _).mul + rw [← dft_odd_iff] at hΦ + exact differentiable_completedLFunction hΦ.map_zero hΦ.sum_eq_zero + -- set where we know equality + have : {z | 1 < re z} ∈ 𝓝 2 := (continuous_re.isOpen_preimage _ isOpen_Ioi).mem_nhds (by simp) + have hFG : F =ᶠ[𝓝 2] G := by filter_upwards [this] with t ht + using completedLFunction_one_sub_of_one_lt_odd hΦ ht + -- now apply the big hammer to finish + rw [← analyticOn_univ_iff_differentiable] at hF hG + exact congr_fun (hF.eq_of_eventuallyEq hG hFG) s + +end signed + end ZMod From c8f01e7871bb38d410c18e08465acd855c1d2ce6 Mon Sep 17 00:00:00 2001 From: Jujian Zhang Date: Thu, 19 Sep 2024 20:23:04 +0000 Subject: [PATCH 057/170] feat: definition of a simple ring (#14503) Co-authored-by: zjj --- Mathlib.lean | 2 + Mathlib/RingTheory/SimpleRing/Basic.lean | 87 +++++++++++++++++++ Mathlib/RingTheory/SimpleRing/Defs.lean | 25 ++++++ Mathlib/RingTheory/TwoSidedIdeal/Basic.lean | 4 + Mathlib/RingTheory/TwoSidedIdeal/Lattice.lean | 6 ++ 5 files changed, 124 insertions(+) create mode 100644 Mathlib/RingTheory/SimpleRing/Basic.lean create mode 100644 Mathlib/RingTheory/SimpleRing/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index 25ed629a1b106..3923b9cd63daa 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4038,6 +4038,8 @@ import Mathlib.RingTheory.RootsOfUnity.Complex import Mathlib.RingTheory.RootsOfUnity.Lemmas import Mathlib.RingTheory.RootsOfUnity.Minpoly import Mathlib.RingTheory.SimpleModule +import Mathlib.RingTheory.SimpleRing.Basic +import Mathlib.RingTheory.SimpleRing.Defs import Mathlib.RingTheory.Smooth.Basic import Mathlib.RingTheory.Smooth.Kaehler import Mathlib.RingTheory.Smooth.StandardSmooth diff --git a/Mathlib/RingTheory/SimpleRing/Basic.lean b/Mathlib/RingTheory/SimpleRing/Basic.lean new file mode 100644 index 0000000000000..c9f5a875cc0b8 --- /dev/null +++ b/Mathlib/RingTheory/SimpleRing/Basic.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2024 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jujian Zhang +-/ + +import Mathlib.RingTheory.SimpleRing.Defs +import Mathlib.Algebra.Field.Equiv +import Mathlib.Algebra.Ring.Subring.Basic + +/-! # Basic Properties of Simple rings + +A ring `R` is **simple** if it has only two two-sided ideals, namely `⊥` and `⊤`. + +## Main results + +- `IsSimpleRing.nontrivial`: simple rings are non-trivial. +- `DivisionRing.IsSimpleRing`: division rings are simple. +- `IsSimpleRing.center_isField`: the center of a simple ring is a field. + +-/ + +variable (R : Type*) [NonUnitalNonAssocRing R] + +namespace IsSimpleRing + +variable {R} + +instance [IsSimpleRing R] : IsSimpleOrder (TwoSidedIdeal R) := IsSimpleRing.simple + +instance [simple : IsSimpleRing R] : Nontrivial R := by + obtain ⟨x, hx⟩ := SetLike.exists_of_lt (bot_lt_top : (⊥ : TwoSidedIdeal R) < ⊤) + have h (hx : x = 0) : False := by simp_all [TwoSidedIdeal.zero_mem] + use x, 0, h + +lemma one_mem_of_ne_bot {A : Type*} [NonAssocRing A] [IsSimpleRing A] (I : TwoSidedIdeal A) + (hI : I ≠ ⊥) : (1 : A) ∈ I := + (eq_bot_or_eq_top I).resolve_left hI ▸ ⟨⟩ + +lemma one_mem_of_ne_zero_mem {A : Type*} [NonAssocRing A] [IsSimpleRing A] (I : TwoSidedIdeal A) + {x : A} (hx : x ≠ 0) (hxI : x ∈ I) : (1 : A) ∈ I := + one_mem_of_ne_bot I (by rintro rfl; exact hx hxI) + +lemma of_eq_bot_or_eq_top [Nontrivial R] (h : ∀ I : TwoSidedIdeal R, I = ⊥ ∨ I = ⊤) : + IsSimpleRing R where + simple := { eq_bot_or_eq_top := h } + +instance _root_.DivisionRing.isSimpleRing (A : Type*) [DivisionRing A] : IsSimpleRing A := + .of_eq_bot_or_eq_top <| fun I ↦ by + rw [or_iff_not_imp_left, ← I.one_mem_iff] + intro H + obtain ⟨x, hx1, hx2 : x ≠ 0⟩ := SetLike.exists_of_lt (bot_lt_iff_ne_bot.mpr H : ⊥ < I) + simpa [inv_mul_cancel₀ hx2] using I.mul_mem_left x⁻¹ _ hx1 + +open TwoSidedIdeal in +lemma isField_center (A : Type*) [Ring A] [IsSimpleRing A] : IsField (Subring.center A) where + exists_pair_ne := ⟨0, 1, zero_ne_one⟩ + mul_comm := mul_comm + mul_inv_cancel := by + rintro ⟨x, hx1⟩ hx2 + rw [Subring.mem_center_iff] at hx1 + replace hx2 : x ≠ 0 := by simpa [Subtype.ext_iff] using hx2 + -- Todo: golf the following `let` once `TwoSidedIdeal.span` is defined + let I := TwoSidedIdeal.mk' (Set.range (x * ·)) ⟨0, by simp⟩ + (by rintro _ _ ⟨x, rfl⟩ ⟨y, rfl⟩; exact ⟨x + y, mul_add _ _ _⟩) + (by rintro _ ⟨x, rfl⟩; exact ⟨-x, by simp⟩) + (by rintro a _ ⟨c, rfl⟩; exact ⟨a * c, by dsimp; rw [← mul_assoc, ← hx1, mul_assoc]⟩) + (by rintro _ b ⟨a, rfl⟩; exact ⟨a * b, by dsimp; rw [← mul_assoc, ← hx1, mul_assoc]⟩) + have mem : 1 ∈ I := one_mem_of_ne_zero_mem I hx2 (by simpa [I, mem_mk'] using ⟨1, by simp⟩) + simp only [TwoSidedIdeal.mem_mk', Set.mem_range, I] at mem + obtain ⟨y, hy⟩ := mem + refine ⟨⟨y, Subring.mem_center_iff.2 fun a ↦ ?_⟩, by ext; exact hy⟩ + calc a * y + _ = (x * y) * a * y := by rw [hy, one_mul] + _ = (y * x) * a * y := by rw [hx1] + _ = y * (x * a) * y := by rw [mul_assoc y x a] + _ = y * (a * x) * y := by rw [hx1] + _ = y * ((a * x) * y) := by rw [mul_assoc] + _ = y * (a * (x * y)) := by rw [mul_assoc a x y] + _ = y * a := by rw [hy, mul_one] + +end IsSimpleRing + +lemma isSimpleRing_iff_isField (A : Type*) [CommRing A] : IsSimpleRing A ↔ IsField A := + ⟨fun _ ↦ Subring.topEquiv.symm.toMulEquiv.isField <| by + rw [← Subring.center_eq_top A]; exact IsSimpleRing.isField_center A, + fun h ↦ letI := h.toField; inferInstance⟩ diff --git a/Mathlib/RingTheory/SimpleRing/Defs.lean b/Mathlib/RingTheory/SimpleRing/Defs.lean new file mode 100644 index 0000000000000..ce50f0bbc7460 --- /dev/null +++ b/Mathlib/RingTheory/SimpleRing/Defs.lean @@ -0,0 +1,25 @@ +/- +Copyright (c) 2024 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jujian Zhang +-/ + +import Mathlib.RingTheory.TwoSidedIdeal.Lattice +import Mathlib.Order.Atoms + +/-! # Simple rings + +A ring `R` is **simple** if it has only two two-sided ideals, namely `⊥` and `⊤`. + +## Main definitions + +- `IsSimpleRing`: a predicate expressing that a ring is simple. + +-/ + + +/-- +A ring `R` is **simple** if it has only two two-sided ideals, namely `⊥` and `⊤`. +-/ +class IsSimpleRing (R : Type*) [NonUnitalNonAssocRing R] : Prop where + simple : IsSimpleOrder (TwoSidedIdeal R) diff --git a/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean b/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean index 0358a0fe72767..8be0b86366462 100644 --- a/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean +++ b/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean @@ -45,6 +45,10 @@ section NonUnitalNonAssocRing variable {R : Type*} [NonUnitalNonAssocRing R] (I : TwoSidedIdeal R) +instance [Nontrivial R] : Nontrivial (TwoSidedIdeal R) := by + obtain ⟨I, J, h⟩ : Nontrivial (RingCon R) := inferInstance + exact ⟨⟨I⟩, ⟨J⟩, by contrapose! h; aesop⟩ + instance setLike : SetLike (TwoSidedIdeal R) R where coe t := {r | t.ringCon r 0} coe_injective' := by diff --git a/Mathlib/RingTheory/TwoSidedIdeal/Lattice.lean b/Mathlib/RingTheory/TwoSidedIdeal/Lattice.lean index b767130c1a90b..55d3b2a16a8c7 100644 --- a/Mathlib/RingTheory/TwoSidedIdeal/Lattice.lean +++ b/Mathlib/RingTheory/TwoSidedIdeal/Lattice.lean @@ -132,4 +132,10 @@ instance : CompleteLattice (TwoSidedIdeal R) where le_top _ := by rw [ringCon_le_iff]; exact le_top bot_le _ := by rw [ringCon_le_iff]; exact bot_le +lemma one_mem_iff {R : Type*} [NonAssocRing R] (I : TwoSidedIdeal R) : + (1 : R) ∈ I ↔ I = ⊤ := + ⟨fun h => eq_top_iff.2 fun x _ => by simpa using I.mul_mem_left x _ h, fun h ↦ h.symm ▸ trivial⟩ + +alias ⟨eq_top, one_mem⟩ := one_mem_iff + end TwoSidedIdeal From f0308a5a96ac9f15eacf9fe8994928a8a0e79e86 Mon Sep 17 00:00:00 2001 From: Etienne Date: Thu, 19 Sep 2024 20:54:07 +0000 Subject: [PATCH 058/170] feat: separable measure and sufficient condition for Lp spaces to be second-countable (#12519) Define the notion of measure-dense family in a measure space, and the notion of separable measure. Prove that if a measure is separable and E is a second-countable `NormedAddCommGroup`, then the corresponding Lp space is second-countable. True in particular when the measurable space is countably generated and the measure is s-finite. Co-authored-by: Etienne <66847262+EtienneC30@users.noreply.github.com> --- Mathlib.lean | 1 + .../Measure/SeparableMeasure.lean | 515 ++++++++++++++++++ 2 files changed, 516 insertions(+) create mode 100644 Mathlib/MeasureTheory/Measure/SeparableMeasure.lean diff --git a/Mathlib.lean b/Mathlib.lean index 3923b9cd63daa..20a9a069cf426 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3331,6 +3331,7 @@ import Mathlib.MeasureTheory.Measure.Portmanteau import Mathlib.MeasureTheory.Measure.ProbabilityMeasure import Mathlib.MeasureTheory.Measure.Regular import Mathlib.MeasureTheory.Measure.Restrict +import Mathlib.MeasureTheory.Measure.SeparableMeasure import Mathlib.MeasureTheory.Measure.Stieltjes import Mathlib.MeasureTheory.Measure.Sub import Mathlib.MeasureTheory.Measure.Tilted diff --git a/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean b/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean new file mode 100644 index 0000000000000..a475581af381f --- /dev/null +++ b/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean @@ -0,0 +1,515 @@ +/- +Copyright (c) 2024 Etienne Marion. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Etienne Marion +-/ +import Mathlib.MeasureTheory.Function.SimpleFuncDenseLp +import Mathlib.MeasureTheory.SetAlgebra + +/-! +# Separable measure + +The goal of this file is to give a sufficient condition on the measure space `(X, μ)` and the +`NormedAddCommGroup E` for the space `MeasureTheory.Lp E p μ` to have `SecondCountableTopology` when +`1 ≤ p < ∞`. To do so we define the notion of a `MeasureTheory.MeasureDense` family and a +separable measure (`MeasureTheory.IsSeparable`). +We prove that if `X` is `MeasurableSpace.CountablyGenerated` and `μ` is s-finite, then `μ` +is separable. We then prove that if `μ` is separable and `E` is second-countable, +then `Lp E p μ` is second-countable. + +A family `𝒜` of subsets of `X` is said to be **measure-dense** if it contains only measurable sets +and can approximate any measurable set with finite measure, in the sense that +for any measurable set `s` such that `μ s ≠ ∞`, `μ (s ∆ t)` can be made +arbitrarily small when `t ∈ 𝒜`. We show below that such a family can be chosen to contain only +sets with finite measure. +The term "measure-dense" is justified by the fact that the approximating condition translates +to the usual notion of density in the metric space made by constant indicators of measurable sets +equipped with the `Lᵖ` norm. + +A measure `μ` is **separable** if it admits a countable and measure-dense family of sets. +The term "separable" is justified by the fact that the definition translates to the usual notion +of separability in the metric space made by constant indicators equipped with the `Lᵖ` norm. + +## Main definitions + +* `MeasureTheory.Measure.μ.MeasureDense 𝒜`: `𝒜` is a measure-dense family if it only contains + measurable sets and if the following condition is satisfied: if `s` is measurable with finite + measure, then for any `ε > 0` there exists `t ∈ 𝒜` such that `μ (s ∆ t) < ε `. +* `MeasureTheory.IsSeparable`: A measure is separable if there exists a countable and + measure-dense family. + +## Main statements + +* `MeasureTheory.instSecondCountableLp`: If `μ` is separable, `E` is second-countable and + `1 ≤ p < ∞` then `Lp E p μ` is second-countable. This is in particular true if `X` is countably + generated and `μ` is s-finite. + +## Implementation notes + +Through the whole file we consider a measurable space `X` equipped with a measure `μ`, and also +a normed commutative group `E`. We also consider an extended non-negative real `p` such that +`1 ≤ p < ∞`. This is registered as instances via `one_le_p : Fact (1 ≤ p)` and +`p_ne_top : Fact (p ≠ ∞)`, so the properties are accessible via `one_le_p.elim` and `p_ne_top.elim`. + +Through the whole file, when we write that an extended non-negative real is finite, it is always +written `≠ ∞` rather than `< ∞`. See `Ne.lt_top` and `ne_of_lt` to switch from one to the other. + +## References + +* [D. L. Cohn, *Measure Theory*][cohn2013measure] + +## Tags + +separable measure, measure-dense, Lp space, second-countable +-/ + +open MeasurableSpace Set ENNReal TopologicalSpace BigOperators symmDiff Filter Real + +namespace MeasureTheory + +variable {X E : Type*} [m : MeasurableSpace X] [NormedAddCommGroup E] {μ : Measure X} +variable {p : ℝ≥0∞} [one_le_p : Fact (1 ≤ p)] [p_ne_top : Fact (p ≠ ∞)] {𝒜 : Set (Set X)} + +section MeasureDense + +/-! ### Definition of a measure-dense family, basic properties and sufficient conditions -/ + +/-- A family `𝒜` of sets of a measure space is said to be measure-dense if it contains only +measurable sets and can approximate any measurable set with finite measure, in the sense that +for any measurable set `s` with finite measure the symmetric difference `s ∆ t` can be made +arbitrarily small when `t ∈ 𝒜`. We show below that such a family can be chosen to contain only +sets with finite measures. + +The term "measure-dense" is justified by the fact that the approximating condition translates +to the usual notion of density in the metric space made by constant indicators of measurable sets +equipped with the `Lᵖ` norm. -/ +structure Measure.MeasureDense (μ : Measure X) (𝒜 : Set (Set X)) : Prop := + /-- Each set has to be measurable. -/ + measurable : ∀ s ∈ 𝒜, MeasurableSet s + /-- Any measurable set can be approximated by sets in the family. -/ + approx : ∀ s, MeasurableSet s → μ s ≠ ∞ → ∀ (ε : ℝ), + 0 < ε → ∃ t ∈ 𝒜, μ (s ∆ t) < ENNReal.ofReal ε + +theorem Measure.MeasureDense.nonempty (h𝒜 : μ.MeasureDense 𝒜) : 𝒜.Nonempty := by + rcases h𝒜.approx ∅ MeasurableSet.empty (by simp) 1 (by norm_num) with ⟨t, ht, -⟩ + exact ⟨t, ht⟩ + +theorem Measure.MeasureDense.nonempty' (h𝒜 : μ.MeasureDense 𝒜) : + {s | s ∈ 𝒜 ∧ μ s ≠ ∞}.Nonempty := by + rcases h𝒜.approx ∅ MeasurableSet.empty (by simp) 1 (by norm_num) with ⟨t, ht, hμt⟩ + refine ⟨t, ht, ?_⟩ + convert ne_top_of_lt hμt + rw [← bot_eq_empty, bot_symmDiff] + +/-- The set of measurable sets is measure-dense. -/ +theorem measureDense_measurableSet : μ.MeasureDense {s | MeasurableSet s} where + measurable := fun _ h ↦ h + approx := fun s hs _ ε ε_pos ↦ ⟨s, hs, by simpa⟩ + +/-- If a family of sets `𝒜` is measure-dense in `X`, then any measurable set with finite measure +can be approximated by sets in `𝒜` with finite measure. -/ +lemma Measure.MeasureDense.fin_meas_approx (h𝒜 : μ.MeasureDense 𝒜) {s : Set X} + (ms : MeasurableSet s) (hμs : μ s ≠ ∞) (ε : ℝ) (ε_pos : 0 < ε) : + ∃ t ∈ 𝒜, μ t ≠ ∞ ∧ μ (s ∆ t) < ENNReal.ofReal ε := by + rcases h𝒜.approx s ms hμs ε ε_pos with ⟨t, t_mem, ht⟩ + exact ⟨t, t_mem, (measure_ne_top_iff_of_symmDiff <| ne_top_of_lt ht).1 hμs, ht⟩ + +variable (p) in +/-- If `𝒜` is a measure-dense family of sets and `c : E`, then the set of constant indicators +with constant `c` whose underlying set is in `𝒜` is dense in the set of constant indicators +which are in `Lp E p μ` when `1 ≤ p < ∞`. -/ +theorem Measure.MeasureDense.indicatorConstLp_subset_closure (h𝒜 : μ.MeasureDense 𝒜) (c : E) : + {indicatorConstLp p hs hμs c | (s : Set X) (hs : MeasurableSet s) (hμs : μ s ≠ ∞)} ⊆ + closure {indicatorConstLp p (h𝒜.measurable s hs) hμs c | + (s : Set X) (hs : s ∈ 𝒜) (hμs : μ s ≠ ∞)} := by + obtain rfl | hc := eq_or_ne c 0 + · refine Subset.trans ?_ subset_closure + rintro - ⟨s, ms, hμs, rfl⟩ + obtain ⟨t, ht, hμt⟩ := h𝒜.nonempty' + refine ⟨t, ht, hμt, ?_⟩ + simp_rw [indicatorConstLp] + congr + simp + · have p_pos : 0 < p := lt_of_lt_of_le (by norm_num) one_le_p.elim + rintro - ⟨s, ms, hμs, rfl⟩ + refine Metric.mem_closure_iff.2 fun ε hε ↦ ?_ + have aux : 0 < (ε / ‖c‖) ^ p.toReal := rpow_pos_of_pos (div_pos hε (norm_pos_iff.2 hc)) _ + obtain ⟨t, ht, hμt, hμst⟩ := h𝒜.fin_meas_approx ms hμs ((ε / ‖c‖) ^ p.toReal) aux + refine ⟨indicatorConstLp p (h𝒜.measurable t ht) hμt c, + ⟨t, ht, hμt, rfl⟩, ?_⟩ + rw [dist_indicatorConstLp_eq_norm, norm_indicatorConstLp p_pos.ne.symm p_ne_top.elim] + calc + ‖c‖ * (μ (s ∆ t)).toReal ^ (1 / p.toReal) + < ‖c‖ * (ENNReal.ofReal ((ε / ‖c‖) ^ p.toReal)).toReal ^ (1 / p.toReal) := by + rw [_root_.mul_lt_mul_left (norm_pos_iff.2 hc)] + refine Real.rpow_lt_rpow (by simp) ?_ + (one_div_pos.2 <| toReal_pos p_pos.ne.symm p_ne_top.elim) + rwa [toReal_lt_toReal (measure_symmDiff_ne_top hμs hμt) ofReal_ne_top] + _ = ε := by + rw [toReal_ofReal (rpow_nonneg (div_nonneg hε.le (norm_nonneg _)) _), + one_div, Real.rpow_rpow_inv (div_nonneg hε.le (norm_nonneg _)) + (toReal_pos p_pos.ne.symm p_ne_top.elim).ne.symm, + mul_div_cancel₀ _ (norm_ne_zero_iff.2 hc)] + +/-- If a family of sets `𝒜` is measure-dense in `X`, then it is also the case for the sets in `𝒜` +with finite measure. -/ +theorem Measure.MeasureDense.fin_meas (h𝒜 : μ.MeasureDense 𝒜) : + μ.MeasureDense {s | s ∈ 𝒜 ∧ μ s ≠ ∞} where + measurable := fun s h ↦ h𝒜.measurable s h.1 + approx := by + intro s ms hμs ε ε_pos + rcases Measure.MeasureDense.fin_meas_approx h𝒜 ms hμs ε ε_pos with ⟨t, t_mem, hμt, hμst⟩ + exact ⟨t, ⟨t_mem, hμt⟩, hμst⟩ + +/-- If a measurable space equipped with a finite measure is generated by an algebra of sets, then +this algebra of sets is measure-dense. -/ +theorem Measure.MeasureDense.of_generateFrom_isSetAlgebra_finite [IsFiniteMeasure μ] + (h𝒜 : IsSetAlgebra 𝒜) (hgen : m = MeasurableSpace.generateFrom 𝒜) : μ.MeasureDense 𝒜 where + measurable := fun s hs ↦ hgen ▸ measurableSet_generateFrom hs + approx := by + -- We want to show that any measurable set can be approximated by sets in `𝒜`. To do so, it is + -- enough to show that such sets constitute a `σ`-algebra containing `𝒜`. This is contained in + -- the theorem `generateFrom_induction`. + intro s ms + have : MeasurableSet s ∧ ∀ (ε : ℝ), 0 < ε → ∃ t ∈ 𝒜, (μ (s ∆ t)).toReal < ε := by + apply generateFrom_induction + (p := fun s ↦ MeasurableSet s ∧ ∀ (ε : ℝ), 0 < ε → ∃ t ∈ 𝒜, (μ (s ∆ t)).toReal < ε) + (C := 𝒜) (hs := hgen ▸ ms) + · -- If `t ∈ 𝒜`, then `μ (t ∆ t) = 0` which is less than any `ε > 0`. + exact fun t t_mem ↦ ⟨hgen ▸ measurableSet_generateFrom t_mem, + fun ε ε_pos ↦ ⟨t, t_mem, by simpa⟩⟩ + · -- `∅ ∈ 𝒜` and `μ (∅ ∆ ∅) = 0` which is less than any `ε > 0`. + exact ⟨MeasurableSet.empty, fun ε ε_pos ↦ ⟨∅, h𝒜.empty_mem, by simpa⟩⟩ + · -- If `s` is measurable and `t ∈ 𝒜` such that `μ (s ∆ t) < ε`, then `tᶜ ∈ 𝒜` and + -- `μ (sᶜ ∆ tᶜ) = μ (s ∆ t) < ε` so `sᶜ` can be approximated. + refine fun t ⟨mt, ht⟩ ↦ ⟨mt.compl, fun ε ε_pos ↦ ?_⟩ + rcases ht ε ε_pos with ⟨u, u_mem, hμtcu⟩ + exact ⟨uᶜ, h𝒜.compl_mem u_mem, by rwa [compl_symmDiff_compl]⟩ + · -- Let `(fₙ)` be a sequence of measurable sets and `ε > 0`. + refine fun f hf ↦ ⟨MeasurableSet.iUnion (fun n ↦ (hf n).1), fun ε ε_pos ↦ ?_⟩ + -- We have `μ (⋃ n ≤ N, fₙ) ⟶ μ (⋃ n, fₙ)`. + have := tendsto_measure_iUnion_accumulate (μ := μ) (f := f) + rw [← tendsto_toReal_iff (fun _ ↦ measure_ne_top _ _) (measure_ne_top _ _)] at this + -- So there exists `N` such that `μ (⋃ n, fₙ) - μ (⋃ n ≤ N, fₙ) < ε/2`. + rcases Metric.tendsto_atTop.1 this (ε / 2) (by linarith [ε_pos]) with ⟨N, hN⟩ + -- For any `n ≤ N` there exists `gₙ ∈ 𝒜` such that `μ (fₙ ∆ gₙ) < ε/(2*(N+1))`. + choose g g_mem hg using fun n ↦ (hf n).2 (ε / (2 * (N + 1))) (div_pos ε_pos (by linarith)) + -- Therefore we have + -- `μ ((⋃ n, fₙ) ∆ (⋃ n ≤ N, gₙ))` + -- `≤ μ ((⋃ n, fₙ) ∆ (⋃ n ≤ N, fₙ)) + μ ((⋃ n ≤ N, fₙ) ∆ (⋃ n ≤ N, gₙ))` + -- `< ε/2 + ∑ n ≤ N, μ (fₙ ∆ gₙ)` (see `biSup_symmDiff_biSup_le`) + -- `< ε/2 + (N+1)*ε/(2*(N+1)) = ε/2`. + refine ⟨⋃ n ∈ Finset.range (N + 1), g n, h𝒜.biUnion_mem _ (fun i _ ↦ g_mem i), ?_⟩ + calc + (μ ((⋃ n, f n) ∆ (⋃ n ∈ (Finset.range (N + 1)), g n))).toReal + ≤ (μ ((⋃ n, f n) \ ((⋃ n ∈ (Finset.range (N + 1)), f n)) ∪ + ((⋃ n ∈ (Finset.range (N + 1)), f n) ∆ + (⋃ n ∈ (Finset.range (N + 1)), g ↑n)))).toReal := + toReal_mono (measure_ne_top _ _) + (measure_mono <| symmDiff_of_ge (iUnion_subset <| + fun i ↦ iUnion_subset (fun _ ↦ subset_iUnion f i)) ▸ symmDiff_triangle ..) + _ ≤ (μ ((⋃ n, f n) \ + ((⋃ n ∈ (Finset.range (N + 1)), f n)))).toReal + + (μ ((⋃ n ∈ (Finset.range (N + 1)), f n) ∆ + (⋃ n ∈ (Finset.range (N + 1)), g ↑n))).toReal := by + rw [← toReal_add (measure_ne_top _ _) (measure_ne_top _ _)] + exact toReal_mono (add_ne_top.2 ⟨measure_ne_top _ _, measure_ne_top _ _⟩) <| + measure_union_le _ _ + _ < ε := by + rw [← add_halves ε] + apply _root_.add_lt_add + · rw [measure_diff (h_fin := measure_ne_top _ _), + toReal_sub_of_le (ha := measure_ne_top _ _)] + apply lt_of_le_of_lt (sub_le_dist ..) + simp only [Finset.mem_range, Nat.lt_add_one_iff] + exact (dist_comm (α := ℝ) .. ▸ hN N (le_refl N)) + exact (measure_mono <| iUnion_subset <| + fun i ↦ iUnion_subset (fun _ ↦ subset_iUnion f i)) + exact iUnion_subset <| fun i ↦ iUnion_subset (fun _ ↦ subset_iUnion f i) + exact MeasurableSet.biUnion (countable_coe_iff.1 inferInstance) + (fun n _ ↦ (hf n).1.nullMeasurableSet) + · calc + (μ ((⋃ n ∈ (Finset.range (N + 1)), f n) ∆ + (⋃ n ∈ (Finset.range (N + 1)), g ↑n))).toReal + ≤ (μ (⋃ n ∈ (Finset.range (N + 1)), f n ∆ g n)).toReal := + toReal_mono (measure_ne_top _ _) (measure_mono biSup_symmDiff_biSup_le) + _ ≤ ∑ n in (Finset.range (N + 1)), (μ (f n ∆ g n)).toReal := by + rw [← toReal_sum (fun _ _ ↦ measure_ne_top _ _)] + exact toReal_mono (ne_of_lt <| sum_lt_top.2 fun _ _ ↦ measure_lt_top μ _) + (measure_biUnion_finset_le _ _) + _ < ∑ n in (Finset.range (N + 1)), (ε / (2 * (N + 1))) := + Finset.sum_lt_sum (fun i _ ↦ le_of_lt (hg i)) ⟨0, by simp, hg 0⟩ + _ ≤ ε / 2 := by + simp only [Finset.sum_const, Finset.card_range, nsmul_eq_mul, + Nat.cast_add, Nat.cast_one] + rw [div_mul_eq_div_mul_one_div, ← mul_assoc, mul_comm ((N : ℝ) + 1), + mul_assoc] + exact mul_le_of_le_one_right (by linarith [ε_pos]) <| + le_of_eq <| mul_one_div_cancel <| Nat.cast_add_one_ne_zero _ + rintro - ε ε_pos + rcases this.2 ε ε_pos with ⟨t, t_mem, hμst⟩ + exact ⟨t, t_mem, (lt_ofReal_iff_toReal_lt (measure_ne_top _ _)).2 hμst⟩ + +/-- If a measure space `X` is generated by an algebra of sets which contains a monotone countable +family of sets with finite measure spanning `X` (thus the measure is `σ`-finite), then this algebra +of sets is measure-dense. -/ +theorem Measure.MeasureDense.of_generateFrom_isSetAlgebra_sigmaFinite (h𝒜 : IsSetAlgebra 𝒜) + (S : μ.FiniteSpanningSetsIn 𝒜) (hgen : m = MeasurableSpace.generateFrom 𝒜) : + μ.MeasureDense 𝒜 where + measurable s hs := hgen ▸ measurableSet_generateFrom hs + approx := by + -- We use partial unions of (Sₙ) to get a monotone family spanning `X`. + let T := Accumulate S.set + have T_mem : ∀ n, T n ∈ 𝒜 := fun n ↦ by + simpa using h𝒜.biUnion_mem {k | k ≤ n}.toFinset (fun k _ ↦ S.set_mem k) + have T_finite : ∀ n, μ (T n) < ∞ := fun n ↦ by + simpa using measure_biUnion_lt_top {k | k ≤ n}.toFinset.finite_toSet + (fun k _ ↦ S.finite k) + have T_spanning : ⋃ n, T n = univ := S.spanning ▸ iUnion_accumulate + -- We use the fact that we already know this is true for finite measures. As `⋃ n, T n = X`, + -- we have that `μ ((T n) ∩ s) ⟶ μ s`. + intro s ms hμs ε ε_pos + have mono : Monotone (fun n ↦ (T n) ∩ s) := fun m n hmn ↦ inter_subset_inter_left s + (biUnion_subset_biUnion_left fun k hkm ↦ Nat.le_trans hkm hmn) + have := tendsto_measure_iUnion_atTop (μ := μ) mono + rw [← tendsto_toReal_iff] at this + · -- We can therefore choose `N` such that `μ s - μ ((S N) ∩ s) < ε/2`. + rcases Metric.tendsto_atTop.1 this (ε / 2) (by linarith [ε_pos]) with ⟨N, hN⟩ + have : Fact (μ (T N) < ∞) := Fact.mk <| T_finite N + -- Then we can apply the previous result to the measure `μ ((S N) ∩ •)`. + -- There exists `t ∈ 𝒜` such that `μ ((S N) ∩ (s ∆ t)) < ε/2`. + rcases (Measure.MeasureDense.of_generateFrom_isSetAlgebra_finite + (μ := μ.restrict (T N)) h𝒜 hgen).approx s ms + (ne_of_lt (lt_of_le_of_lt (μ.restrict_apply_le _ s) hμs.lt_top)) + (ε / 2) (by linarith [ε_pos]) + with ⟨t, t_mem, ht⟩ + -- We can then use `t ∩ (S N)`, because `S N ∈ 𝒜` by hypothesis. + -- `μ (s ∆ (t ∩ S N))` + -- `≤ μ (s ∆ (s ∩ S N)) + μ ((s ∩ S N) ∆ (t ∩ S N))` + -- `= μ s - μ (s ∩ S N) + μ (s ∆ t) ∩ S N) < ε`. + refine ⟨t ∩ T N, h𝒜.inter_mem t_mem (T_mem N), ?_⟩ + calc + μ (s ∆ (t ∩ T N)) + ≤ μ (s \ (s ∩ T N)) + μ ((s ∆ t) ∩ T N) := by + rw [← symmDiff_of_le (inter_subset_left ..), symmDiff_comm _ s, + inter_symmDiff_distrib_right] + exact measure_symmDiff_le _ _ _ + _ < ENNReal.ofReal (ε / 2) + ENNReal.ofReal (ε / 2) := by + apply ENNReal.add_lt_add + · rw [measure_diff + (inter_subset_left ..) + (ms.inter (hgen ▸ measurableSet_generateFrom (T_mem N))).nullMeasurableSet + (ne_top_of_le_ne_top hμs (measure_mono (inter_subset_left ..))), + lt_ofReal_iff_toReal_lt (sub_ne_top hμs), + toReal_sub_of_le (measure_mono (inter_subset_left ..)) hμs] + apply lt_of_le_of_lt (sub_le_dist ..) + nth_rw 1 [← univ_inter s] + rw [inter_comm s, dist_comm, ← T_spanning, iUnion_inter _ T] + apply hN N (le_refl _) + · rwa [← μ.restrict_apply' (hgen ▸ measurableSet_generateFrom (T_mem N))] + _ = ENNReal.ofReal ε := by + rw [← ofReal_add (by linarith [ε_pos]) (by linarith [ε_pos]), add_halves] + · exact fun n ↦ ne_top_of_le_ne_top hμs (measure_mono (inter_subset_right ..)) + · exact ne_top_of_le_ne_top hμs + (measure_mono (iUnion_subset (fun i ↦ inter_subset_right ..))) + +end MeasureDense + +section IsSeparable + +/-! ### Definition of a separable measure space, sufficient condition -/ + +/-- A measure `μ` is separable if there exists a countable and measure-dense family of sets. + +The term "separable" is justified by the fact that the definition translates to the usual notion +of separability in the metric space made by constant indicators equipped with the `Lᵖ` norm. -/ +class IsSeparable (μ : Measure X) : Prop := + exists_countable_measureDense : ∃ 𝒜, 𝒜.Countable ∧ μ.MeasureDense 𝒜 + +/-- By definition, a separable measure admits a countable and measure-dense family of sets. -/ +theorem exists_countable_measureDense [IsSeparable μ] : + ∃ 𝒜, 𝒜.Countable ∧ μ.MeasureDense 𝒜 := + IsSeparable.exists_countable_measureDense + +/-- If a measurable space is countably generated and equipped with a `σ`-finite measure, then the +measure is separable. This is not an instance because it is used below to prove the more +general case where `μ` is s-finite. -/ +theorem isSeparable_of_sigmaFinite [CountablyGenerated X] [SigmaFinite μ] : + IsSeparable μ where + exists_countable_measureDense := by + have h := countable_countableGeneratingSet (α := X) + have hgen := generateFrom_countableGeneratingSet (α := X) + let 𝒜 := (countableGeneratingSet X) ∪ {μ.toFiniteSpanningSetsIn.set n | n : ℕ} + have count_𝒜 : 𝒜.Countable := + countable_union.2 ⟨h, countable_iff_exists_subset_range.2 + ⟨μ.toFiniteSpanningSetsIn.set, fun _ hx ↦ hx⟩⟩ + refine ⟨generateSetAlgebra 𝒜, countable_generateSetAlgebra count_𝒜, + Measure.MeasureDense.of_generateFrom_isSetAlgebra_sigmaFinite isSetAlgebra_generateSetAlgebra + { set := μ.toFiniteSpanningSetsIn.set + set_mem := fun n ↦ self_subset_generateSetAlgebra (𝒜 := 𝒜) <| Or.inr ⟨n, rfl⟩ + finite := μ.toFiniteSpanningSetsIn.finite + spanning := μ.toFiniteSpanningSetsIn.spanning } + (le_antisymm ?_ (generateFrom_le (fun s hs ↦ ?_)))⟩ + · rw [← hgen] + exact generateFrom_mono <| le_trans self_subset_generateSetAlgebra <| + generateSetAlgebra_mono <| subset_union_left .. + · induction hs with + | base t t_mem => + rcases t_mem with t_mem | ⟨n, rfl⟩ + · exact hgen ▸ measurableSet_generateFrom t_mem + · exact μ.toFiniteSpanningSetsIn.set_mem n + | empty => exact MeasurableSet.empty + | compl t _ t_mem => exact MeasurableSet.compl t_mem + | union t u _ _ t_mem u_mem => exact MeasurableSet.union t_mem u_mem + +/-- If a measurable space is countably generated and equipped with an s-finite measure, then the +measure is separable. -/ +instance [CountablyGenerated X] [SFinite μ] : IsSeparable μ where + exists_countable_measureDense := by + have := isSeparable_of_sigmaFinite (μ := μ.restrict μ.sigmaFiniteSet) + rcases exists_countable_measureDense (μ := μ.restrict μ.sigmaFiniteSet) with ⟨𝒜, count_𝒜, h𝒜⟩ + let ℬ := {s ∩ μ.sigmaFiniteSet | s ∈ 𝒜} + refine ⟨ℬ, count_𝒜.image (fun s ↦ s ∩ μ.sigmaFiniteSet), ?_, ?_⟩ + · rintro - ⟨s, s_mem, rfl⟩ + exact (h𝒜.measurable s s_mem).inter measurableSet_sigmaFiniteSet + · intro s ms hμs ε ε_pos + rcases restrict_compl_sigmaFiniteSet_eq_zero_or_top μ s with hs | hs + · have : (μ.restrict μ.sigmaFiniteSet) s ≠ ∞ := + ne_top_of_le_ne_top hμs <| μ.restrict_le_self _ + rcases h𝒜.approx s ms this ε ε_pos with ⟨t, t_mem, ht⟩ + refine ⟨t ∩ μ.sigmaFiniteSet, ⟨t, t_mem, rfl⟩, ?_⟩ + rw [← measure_inter_add_diff _ measurableSet_sigmaFiniteSet] + have : μ (s ∆ (t ∩ μ.sigmaFiniteSet) \ μ.sigmaFiniteSet) = 0 := by + rw [diff_eq_compl_inter, inter_symmDiff_distrib_left, ← ENNReal.bot_eq_zero, eq_bot_iff] + calc + μ ((μ.sigmaFiniteSetᶜ ∩ s) ∆ (μ.sigmaFiniteSetᶜ ∩ (t ∩ μ.sigmaFiniteSet))) + ≤ μ ((μ.sigmaFiniteSetᶜ ∩ s) ∪ (μ.sigmaFiniteSetᶜ ∩ (t ∩ μ.sigmaFiniteSet))) := + measure_mono symmDiff_subset_union + _ ≤ μ (μ.sigmaFiniteSetᶜ ∩ s) + μ (μ.sigmaFiniteSetᶜ ∩ (t ∩ μ.sigmaFiniteSet)) := + measure_union_le _ _ + _ = 0 := by + rw [inter_comm, ← μ.restrict_apply ms, hs, ← inter_assoc, inter_comm, ← inter_assoc, + inter_compl_self, empty_inter, measure_empty, zero_add] + rwa [this, add_zero, inter_symmDiff_distrib_right, inter_assoc, inter_self, + ← inter_symmDiff_distrib_right, ← μ.restrict_apply' measurableSet_sigmaFiniteSet] + · refine False.elim <| hμs ?_ + rw [eq_top_iff, ← hs] + exact μ.restrict_le_self _ + +end IsSeparable + +section SecondCountableLp + +/-! ### A sufficient condition for $L^p$ spaces to be second-countable -/ + +/-- If the measure `μ` is separable (in particular if `X` is countably generated and `μ` is +`s`-finite), if `E` is a second-countable `NormedAddCommGroup`, and if `1 ≤ p < +∞`, +then the associated `Lᵖ` space is second-countable. -/ +instance Lp.SecondCountableTopology [IsSeparable μ] [TopologicalSpace.SeparableSpace E] : + SecondCountableTopology (Lp E p μ) := by + -- It is enough to show that the space is separable, i.e. admits a countable and dense susbet. + refine @UniformSpace.secondCountable_of_separable _ _ _ ?_ + -- There exists a countable and measure-dense family, and we can keep only the sets with finite + -- measure while preserving the two properties. This family is denoted `𝒜₀`. + rcases exists_countable_measureDense (μ := μ) with ⟨𝒜, count_𝒜, h𝒜⟩ + have h𝒜₀ := Measure.MeasureDense.fin_meas h𝒜 + set 𝒜₀ := {s | s ∈ 𝒜 ∧ μ s ≠ ∞} + have count_𝒜₀ : 𝒜₀.Countable := count_𝒜.mono fun _ ⟨h, _⟩ ↦ h + -- `1 ≤ p` so `p ≠ 0`, we prove it now as it is often needed. + have p_ne_zero : p ≠ 0 := ne_of_gt <| lt_of_lt_of_le (by norm_num) one_le_p.elim + -- `E` is second-countable, therefore separable and admits a countable and dense subset `u`. + rcases exists_countable_dense E with ⟨u, countable_u, dense_u⟩ + -- The countable and dense subset of `Lᵖ` we are going to build is the set of finite sums of + -- constant indicators with support in `𝒜₀`, and is denoted `D`. To make manipulations easier, + -- we define the function `key` which given an integer `n` and two families of `n` elements + -- in `u` and `𝒜₀` associates the corresponding sum. + let key : (n : ℕ) → (Fin n → u) → (Fin n → 𝒜₀) → (Lp E p μ) := + fun n d s ↦ ∑ i, indicatorConstLp p (h𝒜₀.measurable (s i) (Subtype.mem (s i))) + (s i).2.2 (d i : E) + let D := {s : Lp E p μ | ∃ n d t, s = key n d t} + refine ⟨D, ?_, ?_⟩ + · -- Countability directly follows from countability of `u` and `𝒜₀`. The function `f` below + -- is the uncurryfied version of `key`, which is easier to manipulate as countability of the + -- domain is automatically infered. + let f : (Σ n : ℕ, (Fin n → u) × (Fin n → 𝒜₀)) → Lp E p μ := fun nds ↦ key nds.1 nds.2.1 nds.2.2 + have := count_𝒜₀.to_subtype + have := countable_u.to_subtype + have : D ⊆ range f := by + rintro - ⟨n, d, s, rfl⟩ + use ⟨n, (d, s)⟩ + exact (countable_range f).mono this + · -- Let's turn to the density. Thanks to the density of simple functions in `Lᵖ`, it is enough + -- to show that the closure of `D` contains constant indicators which are in `Lᵖ` (i. e. the + -- set has finite measure), is closed by sum and closed. + -- This is given by `Lp.induction`. + refine Lp.induction p_ne_top.elim (P := fun f ↦ f ∈ closure D) ?_ ?_ isClosed_closure + · intro a s ms hμs + -- We want to approximate `a • 𝟙ₛ`. + apply ne_of_lt at hμs + rw [SeminormedAddCommGroup.mem_closure_iff] + intro ε ε_pos + have μs_pow_nonneg : 0 ≤ (μ s).toReal ^ (1 / p.toReal) := + Real.rpow_nonneg ENNReal.toReal_nonneg _ + -- To do so, we first pick `b ∈ u` such that `‖a - b‖ < ε / (3 * (1 + (μ s)^(1/p)))`. + have approx_a_pos : 0 < ε / (3 * (1 + (μ s).toReal ^ (1 / p.toReal))) := + div_pos ε_pos (by linarith [μs_pow_nonneg]) + have ⟨b, b_mem, hb⟩ := SeminormedAddCommGroup.mem_closure_iff.1 (dense_u a) _ approx_a_pos + -- Then we pick `t ∈ 𝒜₀` such that `‖b • 𝟙ₛ - b • 𝟙ₜ‖ < ε / 3`. + rcases SeminormedAddCommGroup.mem_closure_iff.1 + (h𝒜₀.indicatorConstLp_subset_closure p b ⟨s, ms, hμs, rfl⟩) + (ε / 3) (by linarith [ε_pos]) with ⟨-, ⟨t, ht, hμt, rfl⟩, hst⟩ + have mt := h𝒜₀.measurable t ht + -- We now show that `‖a • 𝟙ₛ - b • 𝟙ₜ‖ₚ < ε`, as follows: + -- `‖a • 𝟙ₛ - b • 𝟙ₜ‖ₚ` + -- `= ‖a • 𝟙ₛ - b • 𝟙ₛ + b • 𝟙ₛ - b • 𝟙ₜ‖ₚ` + -- `≤ ‖a - b‖ * ‖𝟙ₛ‖ₚ + ε / 3` + -- `= ‖a - b‖ * (μ s)^(1/p) + ε / 3` + -- `< ε * (μ s)^(1/p) / (3 * (1 + (μ s)^(1/p))) + ε / 3` + -- `≤ ε / 3 + ε / 3 < ε`. + refine ⟨indicatorConstLp p mt hμt b, + ⟨1, fun _ ↦ ⟨b, b_mem⟩, fun _ ↦ ⟨t, ht⟩, by simp [key]⟩, ?_⟩ + rw [Lp.simpleFunc.coe_indicatorConst, + ← sub_add_sub_cancel _ (indicatorConstLp p ms hμs b), ← add_halves ε] + refine lt_of_le_of_lt (b := ε / 3 + ε / 3) (norm_add_le_of_le ?_ hst.le) (by linarith [ε_pos]) + rw [indicatorConstLp_sub, norm_indicatorConstLp p_ne_zero p_ne_top.elim] + calc + ‖a - b‖ * (μ s).toReal ^ (1 / p.toReal) + ≤ (ε / (3 * (1 + (μ s).toReal ^ (1 / p.toReal)))) * (μ s).toReal ^ (1 / p.toReal) := + mul_le_mul_of_nonneg_right (le_of_lt hb) μs_pow_nonneg + _ ≤ ε / 3 := by + rw [← mul_one (ε / 3), div_mul_eq_div_mul_one_div, mul_assoc, one_div_mul_eq_div] + exact mul_le_mul_of_nonneg_left + ((div_le_one (by linarith [μs_pow_nonneg])).2 (by linarith)) + (by linarith [ε_pos]) + · -- Now we have to show that the closure of `D` is closed by sum. Let `f` and `g` be two + -- functions in `Lᵖ` which are also in the closure of `D`. + rintro f g hf hg - f_mem g_mem + rw [SeminormedAddCommGroup.mem_closure_iff] at * + intro ε ε_pos + -- For `ε > 0`, there exists `bf, bg ∈ D` such that `‖f - bf‖ₚ < ε/2` and `‖g - bg‖ₚ < ε/2`. + rcases f_mem (ε / 2) (by linarith [ε_pos]) with ⟨bf, ⟨nf, df, sf, bf_eq⟩, hbf⟩ + rcases g_mem (ε / 2) (by linarith [ε_pos]) with ⟨bg, ⟨ng, dg, sg, bg_eq⟩, hbg⟩ + -- It is obvious that `D` is closed by sum, it suffices to concatenate the family of + -- elements of `u` and the family of elements of `𝒜₀`. + let d := fun i : Fin (nf + ng) ↦ if h : i < nf + then df (Fin.castLT i h) + else dg (Fin.subNat nf (Fin.cast (Nat.add_comm ..) i) (le_of_not_gt h)) + let s := fun i : Fin (nf + ng) ↦ if h : i < nf + then sf (Fin.castLT i h) + else sg (Fin.subNat nf (Fin.cast (Nat.add_comm ..) i) (le_of_not_gt h)) + -- So we can use `bf + bg`. + refine ⟨bf + bg, ⟨nf + ng, d, s, ?_⟩, ?_⟩ + · simp [key, d, s, Fin.sum_univ_add, bf_eq, bg_eq] + · -- We have + -- `‖f + g - (bf + bg)‖ₚ` + -- `≤ ‖f - bf‖ₚ + ‖g - bg‖ₚ` + -- `< ε/2 + ε/2 = ε`. + calc + ‖Memℒp.toLp f hf + Memℒp.toLp g hg - (bf + bg)‖ + = ‖(Memℒp.toLp f hf) - bf + ((Memℒp.toLp g hg) - bg)‖ := by congr; abel + _ ≤ ‖(Memℒp.toLp f hf) - bf‖ + ‖(Memℒp.toLp g hg) - bg‖ := norm_add_le .. + _ < ε := by linarith [hbf, hbg] + +end SecondCountableLp + +end MeasureTheory From 0f3d1c6a7a968a9cdae51dd12aa04f128c42c661 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 20 Sep 2024 00:43:00 +0000 Subject: [PATCH 059/170] chore: revert holder -> hoelder (#16955) Per https://leanprover.zulipchat.com/#narrow/stream/116290-rss/topic/Recent.20Commits.20to.20mathlib4.3Amaster/near/471490433 --- Mathlib.lean | 4 +- Mathlib/MeasureTheory/Measure/Hausdorff.lean | 11 +- .../{JordanHoelder.lean => JordanHolder.lean} | 44 ++--- Mathlib/RingTheory/SimpleModule.lean | 10 +- .../MetricSpace/HausdorffDimension.lean | 28 ++-- .../MetricSpace/{Hoelder.lean => Holder.lean} | 153 +++++++++--------- docs/overview.yaml | 2 +- docs/undergrad.yaml | 2 +- scripts/nolints.json | 4 +- 9 files changed, 128 insertions(+), 130 deletions(-) rename Mathlib/Order/{JordanHoelder.lean => JordanHolder.lean} (92%) rename Mathlib/Topology/MetricSpace/{Hoelder.lean => Holder.lean} (53%) diff --git a/Mathlib.lean b/Mathlib.lean index 20a9a069cf426..1dd73c2e11a79 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3657,7 +3657,7 @@ import Mathlib.Order.Interval.Set.WithBotTop import Mathlib.Order.Irreducible import Mathlib.Order.IsWellOrderLimitElement import Mathlib.Order.Iterate -import Mathlib.Order.JordanHoelder +import Mathlib.Order.JordanHolder import Mathlib.Order.KonigLemma import Mathlib.Order.KrullDimension import Mathlib.Order.Lattice @@ -4661,7 +4661,7 @@ import Mathlib.Topology.MetricSpace.GromovHausdorff import Mathlib.Topology.MetricSpace.GromovHausdorffRealized import Mathlib.Topology.MetricSpace.HausdorffDimension import Mathlib.Topology.MetricSpace.HausdorffDistance -import Mathlib.Topology.MetricSpace.Hoelder +import Mathlib.Topology.MetricSpace.Holder import Mathlib.Topology.MetricSpace.Infsep import Mathlib.Topology.MetricSpace.IsometricSMul import Mathlib.Topology.MetricSpace.Isometry diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 9c35a5a589469..84bfe07b9e3fb 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -6,7 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Analysis.Convex.Between import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic import Mathlib.MeasureTheory.Measure.Lebesgue.Basic -import Mathlib.Topology.MetricSpace.Hoelder +import Mathlib.Topology.MetricSpace.Holder import Mathlib.Topology.MetricSpace.MetricSeparated /-! @@ -667,13 +667,13 @@ open MeasureTheory MeasureTheory.Measure variable [MeasurableSpace X] [BorelSpace X] [MeasurableSpace Y] [BorelSpace Y] -namespace HoelderOnWith +namespace HolderOnWith variable {C r : ℝ≥0} {f : X → Y} {s t : Set X} /-- If `f : X → Y` is Hölder continuous on `s` with a positive exponent `r`, then `μH[d] (f '' s) ≤ C ^ d * μH[r * d] s`. -/ -theorem hausdorffMeasure_image_le (h : HoelderOnWith C r f s) (hr : 0 < r) {d : ℝ} (hd : 0 ≤ d) : +theorem hausdorffMeasure_image_le (h : HolderOnWith C r f s) (hr : 0 < r) {d : ℝ} (hd : 0 ≤ d) : μH[d] (f '' s) ≤ (C : ℝ≥0∞) ^ d * μH[r * d] s := by -- We start with the trivial case `C = 0` rcases (zero_le C).eq_or_lt with (rfl | hC0) @@ -711,7 +711,7 @@ theorem hausdorffMeasure_image_le (h : HoelderOnWith C r f s) (hr : 0 < r) {d : rw [ENNReal.rpow_mul, ← ENNReal.mul_rpow_of_nonneg _ _ hd] exact ENNReal.rpow_le_rpow (h.ediam_image_inter_le _) hd -end HoelderOnWith +end HolderOnWith namespace LipschitzOnWith @@ -720,8 +720,7 @@ variable {K : ℝ≥0} {f : X → Y} {s t : Set X} /-- If `f : X → Y` is `K`-Lipschitz on `s`, then `μH[d] (f '' s) ≤ K ^ d * μH[d] s`. -/ theorem hausdorffMeasure_image_le (h : LipschitzOnWith K f s) {d : ℝ} (hd : 0 ≤ d) : μH[d] (f '' s) ≤ (K : ℝ≥0∞) ^ d * μH[d] s := by - simpa only [NNReal.coe_one, one_mul] - using h.HoelderOnWith.hausdorffMeasure_image_le zero_lt_one hd + simpa only [NNReal.coe_one, one_mul] using h.holderOnWith.hausdorffMeasure_image_le zero_lt_one hd end LipschitzOnWith diff --git a/Mathlib/Order/JordanHoelder.lean b/Mathlib/Order/JordanHolder.lean similarity index 92% rename from Mathlib/Order/JordanHoelder.lean rename to Mathlib/Order/JordanHolder.lean index 0ac4f362de12e..5657d2eff114d 100644 --- a/Mathlib/Order/JordanHoelder.lean +++ b/Mathlib/Order/JordanHolder.lean @@ -13,16 +13,16 @@ import Mathlib.Order.RelSeries /-! # Jordan-Hölder Theorem -This file proves the Jordan Hölder theorem for a `JordanHoelderLattice`, a class also defined in -this file. Examples of `JordanHoelderLattice` include `Subgroup G` if `G` is a group, and +This file proves the Jordan Hölder theorem for a `JordanHolderLattice`, a class also defined in +this file. Examples of `JordanHolderLattice` include `Subgroup G` if `G` is a group, and `Submodule R M` if `M` is an `R`-module. Using this approach the theorem need not be proved separately for both groups and modules, the proof in this file can be applied to both. ## Main definitions -The main definitions in this file are `JordanHoelderLattice` and `CompositionSeries`, +The main definitions in this file are `JordanHolderLattice` and `CompositionSeries`, and the relation `Equivalent` on `CompositionSeries` -A `JordanHoelderLattice` is the class for which the Jordan Hölder theorem is proved. A +A `JordanHolderLattice` is the class for which the Jordan Hölder theorem is proved. A Jordan Hölder lattice is a lattice equipped with a notion of maximality, `IsMaximal`, and a notion of isomorphism of pairs `Iso`. In the example of subgroups of a group, `IsMaximal H K` means that `H` is a maximal normal subgroup of `K`, and `Iso (H₁, K₁) (H₂, K₂)` means that the quotient @@ -42,30 +42,30 @@ Two `CompositionSeries X`, `s₁` and `s₂` are equivalent if there is a biject ## Main theorems -The main theorem is `CompositionSeries.jordan_hoelder`, which says that if two composition +The main theorem is `CompositionSeries.jordan_holder`, which says that if two composition series have the same least element and the same largest element, then they are `Equivalent`. ## TODO -Provide instances of `JordanHoelderLattice` for subgroups, and potentially for modular lattices. +Provide instances of `JordanHolderLattice` for subgroups, and potentially for modular lattices. It is not entirely clear how this should be done. Possibly there should be no global instances -of `JordanHoelderLattice`, and the instances should only be defined locally in order to prove +of `JordanHolderLattice`, and the instances should only be defined locally in order to prove the Jordan-Hölder theorem for modules/groups and the API should be transferred because many of the theorems in this file will have stronger versions for modules. There will also need to be an API for mapping composition series across homomorphisms. It is also probably possible to -provide an instance of `JordanHoelderLattice` for any `ModularLattice`, and in this case the +provide an instance of `JordanHolderLattice` for any `ModularLattice`, and in this case the Jordan-Hölder theorem will say that there is a well defined notion of length of a modular lattice. -However an instance of `JordanHoelderLattice` for a modular lattice will not be able to contain +However an instance of `JordanHolderLattice` for a modular lattice will not be able to contain the correct notion of isomorphism for modules, so a separate instance for modules will still be required and this will clash with the instance for modular lattices, and so at least one of these instances should not be a global instance. > [!NOTE] -> The previous paragraph indicates that the instance of `JordanHoelderLattice` for submodules should +> The previous paragraph indicates that the instance of `JordanHolderLattice` for submodules should > be obtained via `ModularLattice`. This is not the case in `mathlib4`. -> See `JordanHoelderModule.instJordanHoelderLattice`. +> See `JordanHolderModule.instJordanHolderLattice`. -/ @@ -73,7 +73,7 @@ universe u open Set RelSeries -/-- A `JordanHoelderLattice` is the class for which the Jordan Hölder theorem is proved. A +/-- A `JordanHolderLattice` is the class for which the Jordan Hölder theorem is proved. A Jordan Hölder lattice is a lattice equipped with a notion of maximality, `IsMaximal`, and a notion of isomorphism of pairs `Iso`. In the example of subgroups of a group, `IsMaximal H K` means that `H` is a maximal normal subgroup of `K`, and `Iso (H₁, K₁) (H₂, K₂)` means that the quotient @@ -81,7 +81,7 @@ of isomorphism of pairs `Iso`. In the example of subgroups of a group, `IsMaxima satisfy the second isomorphism theorem `Iso (H, H ⊔ K) (H ⊓ K, K)`. Examples include `Subgroup G` if `G` is a group, and `Submodule R M` if `M` is an `R`-module. -/ -class JordanHoelderLattice (X : Type u) [Lattice X] where +class JordanHolderLattice (X : Type u) [Lattice X] where IsMaximal : X → X → Prop lt_of_isMaximal : ∀ {x y}, IsMaximal x y → x < y sup_eq_of_isMaximal : ∀ {x y z}, IsMaximal x z → IsMaximal y z → x ≠ y → x ⊔ y = z @@ -92,9 +92,9 @@ class JordanHoelderLattice (X : Type u) [Lattice X] where iso_trans : ∀ {x y z}, Iso x y → Iso y z → Iso x z second_iso : ∀ {x y}, IsMaximal x (x ⊔ y) → Iso (x, x ⊔ y) (x ⊓ y, y) -namespace JordanHoelderLattice +namespace JordanHolderLattice -variable {X : Type u} [Lattice X] [JordanHoelderLattice X] +variable {X : Type u} [Lattice X] [JordanHolderLattice X] theorem isMaximal_inf_right_of_isMaximal_sup {x y : X} (hxz : IsMaximal x (x ⊔ y)) (hyz : IsMaximal y (x ⊔ y)) : IsMaximal (x ⊓ y) y := by @@ -115,27 +115,27 @@ theorem IsMaximal.iso_refl {x y : X} (h : IsMaximal x y) : Iso (x, y) (x, y) := second_iso_of_eq h (sup_eq_right.2 (le_of_lt (lt_of_isMaximal h))) (inf_eq_left.2 (le_of_lt (lt_of_isMaximal h))) -end JordanHoelderLattice +end JordanHolderLattice -open JordanHoelderLattice +open JordanHolderLattice attribute [symm] iso_symm attribute [trans] iso_trans /-- A `CompositionSeries X` is a finite nonempty series of elements of a -`JordanHoelderLattice` such that each element is maximal inside the next. The length of a +`JordanHolderLattice` such that each element is maximal inside the next. The length of a `CompositionSeries X` is one less than the number of elements in the series. Note that there is no stipulation that a series start from the bottom of the lattice and finish at the top. For a composition series `s`, `s.last` is the largest element of the series, and `s.head` is the least element. -/ -abbrev CompositionSeries (X : Type u) [Lattice X] [JordanHoelderLattice X] : Type u := +abbrev CompositionSeries (X : Type u) [Lattice X] [JordanHolderLattice X] : Type u := RelSeries (IsMaximal (X := X)) namespace CompositionSeries -variable {X : Type u} [Lattice X] [JordanHoelderLattice X] +variable {X : Type u} [Lattice X] [JordanHolderLattice X] theorem lt_succ (s : CompositionSeries X) (i : Fin s.length) : s (Fin.castSucc i) < s (Fin.succ i) := @@ -407,9 +407,9 @@ theorem exists_last_eq_snoc_equivalent (s : CompositionSeries X) (x : X) (hm : I (second_iso_of_eq (isMaximal_eraseLast_last h0s) (sup_eq_of_isMaximal (isMaximal_eraseLast_last h0s) hm hetx) (by rw [inf_comm, htt])) -/-- The **Jordan-Hölder** theorem, stated for any `JordanHoelderLattice`. +/-- The **Jordan-Hölder** theorem, stated for any `JordanHolderLattice`. If two composition series start and finish at the same place, they are equivalent. -/ -theorem jordan_hoelder (s₁ s₂ : CompositionSeries X) +theorem jordan_holder (s₁ s₂ : CompositionSeries X) (hb : s₁.head = s₂.head) (ht : s₁.last = s₂.last) : Equivalent s₁ s₂ := by induction' hle : s₁.length with n ih generalizing s₁ s₂ diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 29555b158d300..5bc001188d6d1 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -5,7 +5,7 @@ Authors: Aaron Anderson -/ import Mathlib.LinearAlgebra.Isomorphisms import Mathlib.LinearAlgebra.Projection -import Mathlib.Order.JordanHoelder +import Mathlib.Order.JordanHolder import Mathlib.Order.CompactlyGenerated.Intervals import Mathlib.LinearAlgebra.FiniteDimensional @@ -405,9 +405,9 @@ noncomputable instance _root_.Module.End.divisionRing end LinearMap -- Porting note: adding a namespace with all the new statements; existing result is not used in ML3 -namespace JordanHoelderModule +namespace JordanHolderModule --- Porting note: jordanHoelderModule was timing out so outlining the fields +-- Porting note: jordanHolderModule was timing out so outlining the fields /-- An isomorphism `X₂ / X₁ ∩ X₂ ≅ Y₂ / Y₁ ∩ Y₂` of modules for pairs `(X₁,X₂) (Y₁,Y₂) : Submodule R M` -/ @@ -428,7 +428,7 @@ theorem second_iso {X Y : Submodule R M} (_ : X ⋖ X ⊔ Y) : dsimp exact (LinearMap.quotientInfEquivSupQuotient Y X).symm -instance instJordanHoelderLattice : JordanHoelderLattice (Submodule R M) where +instance instJordanHolderLattice : JordanHolderLattice (Submodule R M) where IsMaximal := (· ⋖ ·) lt_of_isMaximal := CovBy.lt sup_eq_of_isMaximal hxz hyz := WCovBy.sup_eq hxz.wcovBy hyz.wcovBy @@ -438,4 +438,4 @@ instance instJordanHoelderLattice : JordanHoelderLattice (Submodule R M) where iso_trans := iso_trans second_iso := second_iso -end JordanHoelderModule +end JordanHolderModule diff --git a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean index d2b889b56f214..1018155f553a7 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean @@ -40,9 +40,9 @@ properties of Hausdorff dimension. ### (Pre)images under (anti)lipschitz and Hölder continuous maps -* `HoelderWith.dimH_image_le` etc: if `f : X → Y` is Hölder continuous with exponent `r > 0`, then - for any `s`, `dimH (f '' s) ≤ dimH s / r`. We prove versions of this statement for `HoelderWith`, - `HoelderOnWith`, and locally Hölder maps, as well as for `Set.image` and `Set.range`. +* `HolderWith.dimH_image_le` etc: if `f : X → Y` is Hölder continuous with exponent `r > 0`, then + for any `s`, `dimH (f '' s) ≤ dimH s / r`. We prove versions of this statement for `HolderWith`, + `HolderOnWith`, and locally Hölder maps, as well as for `Set.image` and `Set.range`. * `LipschitzWith.dimH_image_le` etc: Lipschitz continuous maps do not increase the Hausdorff dimension of sets. * for a map that is known to be both Lipschitz and antilipschitz (e.g., for an `Isometry` or @@ -257,7 +257,7 @@ end variable {C K r : ℝ≥0} {f : X → Y} {s t : Set X} /-- If `f` is a Hölder continuous map with exponent `r > 0`, then `dimH (f '' s) ≤ dimH s / r`. -/ -theorem HoelderOnWith.dimH_image_le (h : HoelderOnWith C r f s) (hr : 0 < r) : +theorem HolderOnWith.dimH_image_le (h : HolderOnWith C r f s) (hr : 0 < r) : dimH (f '' s) ≤ dimH s / r := by borelize X Y refine dimH_le fun d hd => ?_ @@ -270,28 +270,28 @@ theorem HoelderOnWith.dimH_image_le (h : HoelderOnWith C r f s) (hr : 0 < r) : exacts [le_dimH_of_hausdorffMeasure_eq_top Hrd, Or.inl (mt ENNReal.coe_eq_zero.1 hr.ne'), Or.inl ENNReal.coe_ne_top] -namespace HoelderWith +namespace HolderWith /-- If `f : X → Y` is Hölder continuous with a positive exponent `r`, then the Hausdorff dimension of the image of a set `s` is at most `dimH s / r`. -/ -theorem dimH_image_le (h : HoelderWith C r f) (hr : 0 < r) (s : Set X) : +theorem dimH_image_le (h : HolderWith C r f) (hr : 0 < r) (s : Set X) : dimH (f '' s) ≤ dimH s / r := - (h.HoelderOnWith s).dimH_image_le hr + (h.holderOnWith s).dimH_image_le hr /-- If `f` is a Hölder continuous map with exponent `r > 0`, then the Hausdorff dimension of its range is at most the Hausdorff dimension of its domain divided by `r`. -/ -theorem dimH_range_le (h : HoelderWith C r f) (hr : 0 < r) : +theorem dimH_range_le (h : HolderWith C r f) (hr : 0 < r) : dimH (range f) ≤ dimH (univ : Set X) / r := @image_univ _ _ f ▸ h.dimH_image_le hr univ -end HoelderWith +end HolderWith /-- If `s` is a set in a space `X` with second countable topology and `f : X → Y` is Hölder continuous in a neighborhood within `s` of every point `x ∈ s` with the same positive exponent `r` but possibly different coefficients, then the Hausdorff dimension of the image `f '' s` is at most the Hausdorff dimension of `s` divided by `r`. -/ theorem dimH_image_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ≥0} {f : X → Y} - (hr : 0 < r) {s : Set X} (hf : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HoelderOnWith C r f t) : + (hr : 0 < r) {s : Set X} (hf : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HolderOnWith C r f t) : dimH (f '' s) ≤ dimH s / r := by choose! C t htn hC using hf rcases countable_cover_nhdsWithin htn with ⟨u, hus, huc, huU⟩ @@ -303,7 +303,7 @@ theorem dimH_image_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ positive exponent `r` but possibly different coefficients, then the Hausdorff dimension of the range of `f` is at most the Hausdorff dimension of `X` divided by `r`. -/ theorem dimH_range_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ≥0} {f : X → Y} - (hr : 0 < r) (hf : ∀ x : X, ∃ C : ℝ≥0, ∃ s ∈ 𝓝 x, HoelderOnWith C r f s) : + (hr : 0 < r) (hf : ∀ x : X, ∃ C : ℝ≥0, ∃ s ∈ 𝓝 x, HolderOnWith C r f s) : dimH (range f) ≤ dimH (univ : Set X) / r := by rw [← image_univ] refine dimH_image_le_of_locally_holder_on hr fun x _ => ?_ @@ -316,7 +316,7 @@ theorem dimH_range_le_of_locally_holder_on [SecondCountableTopology X] {r : ℝ /-- If `f : X → Y` is Lipschitz continuous on `s`, then `dimH (f '' s) ≤ dimH s`. -/ theorem LipschitzOnWith.dimH_image_le (h : LipschitzOnWith K f s) : dimH (f '' s) ≤ dimH s := by - simpa using h.HoelderOnWith.dimH_image_le zero_lt_one + simpa using h.holderOnWith.dimH_image_le zero_lt_one namespace LipschitzWith @@ -336,8 +336,8 @@ is Lipschitz in a neighborhood within `s` of every point `x ∈ s`, then the Hau the image `f '' s` is at most the Hausdorff dimension of `s`. -/ theorem dimH_image_le_of_locally_lipschitzOn [SecondCountableTopology X] {f : X → Y} {s : Set X} (hf : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, LipschitzOnWith C f t) : dimH (f '' s) ≤ dimH s := by - have : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HoelderOnWith C 1 f t := by - simpa only [hoelderOnWith_one] using hf + have : ∀ x ∈ s, ∃ C : ℝ≥0, ∃ t ∈ 𝓝[s] x, HolderOnWith C 1 f t := by + simpa only [holderOnWith_one] using hf simpa only [ENNReal.coe_one, div_one] using dimH_image_le_of_locally_holder_on zero_lt_one this /-- If `f : X → Y` is Lipschitz in a neighborhood of each point `x : X`, then the Hausdorff diff --git a/Mathlib/Topology/MetricSpace/Hoelder.lean b/Mathlib/Topology/MetricSpace/Holder.lean similarity index 53% rename from Mathlib/Topology/MetricSpace/Hoelder.lean rename to Mathlib/Topology/MetricSpace/Holder.lean index 0aeb043310269..da0e2b14c4f81 100644 --- a/Mathlib/Topology/MetricSpace/Hoelder.lean +++ b/Mathlib/Topology/MetricSpace/Holder.lean @@ -14,9 +14,9 @@ properties of Hölder continuous functions. ## Main definitions -* `HoelderOnWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and +* `HolderOnWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and exponent `r : ℝ≥0` on a set `s`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y ∈ s`; -* `HoelderWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and exponent +* `HolderWith`: `f : X → Y` is said to be *Hölder continuous* with constant `C : ℝ≥0` and exponent `r : ℝ≥0`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y : X`. ## Implementation notes @@ -41,82 +41,81 @@ open NNReal ENNReal Topology section Emetric -variable [PseudoEMetricSpace X] [PseudoEMetricSpace Y] [PseudoEMetricSpace Z] {C r : ℝ≥0} - {f : X → Y} +variable [PseudoEMetricSpace X] [PseudoEMetricSpace Y] [PseudoEMetricSpace Z] /-- A function `f : X → Y` between two `PseudoEMetricSpace`s is Hölder continuous with constant `C : ℝ≥0` and exponent `r : ℝ≥0`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y : X`. -/ -def HoelderWith (C r : ℝ≥0) (f : X → Y) : Prop := +def HolderWith (C r : ℝ≥0) (f : X → Y) : Prop := ∀ x y, edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) /-- A function `f : X → Y` between two `PseudoEMetricSpace`s is Hölder continuous with constant `C : ℝ≥0` and exponent `r : ℝ≥0` on a set `s : Set X`, if `edist (f x) (f y) ≤ C * edist x y ^ r` for all `x y ∈ s`. -/ -def HoelderOnWith (C r : ℝ≥0) (f : X → Y) (s : Set X) : Prop := +def HolderOnWith (C r : ℝ≥0) (f : X → Y) (s : Set X) : Prop := ∀ x ∈ s, ∀ y ∈ s, edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) @[simp] -theorem hoelderOnWith_empty (C r : ℝ≥0) (f : X → Y) : HoelderOnWith C r f ∅ := fun _ hx => hx.elim +theorem holderOnWith_empty (C r : ℝ≥0) (f : X → Y) : HolderOnWith C r f ∅ := fun _ hx => hx.elim @[simp] -theorem hoelderOnWith_singleton (C r : ℝ≥0) (f : X → Y) (x : X) : HoelderOnWith C r f {x} := by +theorem holderOnWith_singleton (C r : ℝ≥0) (f : X → Y) (x : X) : HolderOnWith C r f {x} := by rintro a (rfl : a = x) b (rfl : b = a) rw [edist_self] exact zero_le _ -theorem Set.Subsingleton.HoelderOnWith {s : Set X} (hs : s.Subsingleton) (C r : ℝ≥0) (f : X → Y) : - HoelderOnWith C r f s := - hs.induction_on (hoelderOnWith_empty C r f) (hoelderOnWith_singleton C r f) +theorem Set.Subsingleton.holderOnWith {s : Set X} (hs : s.Subsingleton) (C r : ℝ≥0) (f : X → Y) : + HolderOnWith C r f s := + hs.induction_on (holderOnWith_empty C r f) (holderOnWith_singleton C r f) -lemma hoelderOnWith_univ : HoelderOnWith C r f univ ↔ HoelderWith C r f := by - simp only [HoelderOnWith, HoelderWith, mem_univ, true_imp_iff] +theorem holderOnWith_univ {C r : ℝ≥0} {f : X → Y} : HolderOnWith C r f univ ↔ HolderWith C r f := by + simp only [HolderOnWith, HolderWith, mem_univ, true_imp_iff] @[simp] -theorem hoelderOnWith_one {C : ℝ≥0} {f : X → Y} {s : Set X} : - HoelderOnWith C 1 f s ↔ LipschitzOnWith C f s := by - simp only [HoelderOnWith, LipschitzOnWith, NNReal.coe_one, ENNReal.rpow_one] +theorem holderOnWith_one {C : ℝ≥0} {f : X → Y} {s : Set X} : + HolderOnWith C 1 f s ↔ LipschitzOnWith C f s := by + simp only [HolderOnWith, LipschitzOnWith, NNReal.coe_one, ENNReal.rpow_one] -alias ⟨_, LipschitzOnWith.HoelderOnWith⟩ := hoelderOnWith_one +alias ⟨_, LipschitzOnWith.holderOnWith⟩ := holderOnWith_one @[simp] -theorem hoelderWith_one {C : ℝ≥0} {f : X → Y} : HoelderWith C 1 f ↔ LipschitzWith C f := - hoelderOnWith_univ.symm.trans <| hoelderOnWith_one.trans lipschitzOnWith_univ +theorem holderWith_one {C : ℝ≥0} {f : X → Y} : HolderWith C 1 f ↔ LipschitzWith C f := + holderOnWith_univ.symm.trans <| holderOnWith_one.trans lipschitzOnWith_univ -alias ⟨_, LipschitzWith.HoelderWith⟩ := hoelderWith_one +alias ⟨_, LipschitzWith.holderWith⟩ := holderWith_one -theorem hoelderWith_id : HoelderWith 1 1 (id : X → X) := - LipschitzWith.id.HoelderWith +theorem holderWith_id : HolderWith 1 1 (id : X → X) := + LipschitzWith.id.holderWith -protected theorem HoelderWith.HoelderOnWith {C r : ℝ≥0} {f : X → Y} (h : HoelderWith C r f) - (s : Set X) : HoelderOnWith C r f s := fun x _ y _ => h x y +protected theorem HolderWith.holderOnWith {C r : ℝ≥0} {f : X → Y} (h : HolderWith C r f) + (s : Set X) : HolderOnWith C r f s := fun x _ y _ => h x y -namespace HoelderOnWith +namespace HolderOnWith variable {C r : ℝ≥0} {f : X → Y} {s t : Set X} -theorem edist_le (h : HoelderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) : +theorem edist_le (h : HolderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) := h x hx y hy -theorem edist_le_of_le (h : HoelderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) {d : ℝ≥0∞} +theorem edist_le_of_le (h : HolderOnWith C r f s) {x y : X} (hx : x ∈ s) (hy : y ∈ s) {d : ℝ≥0∞} (hd : edist x y ≤ d) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := (h.edist_le hx hy).trans <| by gcongr -theorem comp {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HoelderOnWith Cg rg g t) {Cf rf : ℝ≥0} - {f : X → Y} (hf : HoelderOnWith Cf rf f s) (hst : MapsTo f s t) : - HoelderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := by +theorem comp {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HolderOnWith Cg rg g t) {Cf rf : ℝ≥0} + {f : X → Y} (hf : HolderOnWith Cf rf f s) (hst : MapsTo f s t) : + HolderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := by intro x hx y hy rw [ENNReal.coe_mul, mul_comm rg, NNReal.coe_mul, ENNReal.rpow_mul, mul_assoc, ENNReal.coe_rpow_of_nonneg _ rg.coe_nonneg, ← ENNReal.mul_rpow_of_nonneg _ _ rg.coe_nonneg] exact hg.edist_le_of_le (hst hx) (hst hy) (hf.edist_le hx hy) -theorem comp_hoelderWith {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HoelderOnWith Cg rg g t) - {Cf rf : ℝ≥0} {f : X → Y} (hf : HoelderWith Cf rf f) (ht : ∀ x, f x ∈ t) : - HoelderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := - hoelderOnWith_univ.mp <| hg.comp (hf.HoelderOnWith univ) fun x _ => ht x +theorem comp_holderWith {Cg rg : ℝ≥0} {g : Y → Z} {t : Set Y} (hg : HolderOnWith Cg rg g t) + {Cf rf : ℝ≥0} {f : X → Y} (hf : HolderWith Cf rf f) (ht : ∀ x, f x ∈ t) : + HolderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := + holderOnWith_univ.mp <| hg.comp (hf.holderOnWith univ) fun x _ => ht x /-- A Hölder continuous function is uniformly continuous -/ -protected theorem uniformContinuousOn (hf : HoelderOnWith C r f s) (h0 : 0 < r) : +protected theorem uniformContinuousOn (hf : HolderOnWith C r f s) (h0 : 0 < r) : UniformContinuousOn f s := by refine EMetric.uniformContinuousOn_iff.2 fun ε εpos => ?_ have : Tendsto (fun d : ℝ≥0∞ => (C : ℝ≥0∞) * d ^ (r : ℝ)) (𝓝 0) (𝓝 0) := @@ -124,86 +123,86 @@ protected theorem uniformContinuousOn (hf : HoelderOnWith C r f s) (h0 : 0 < r) rcases ENNReal.nhds_zero_basis.mem_iff.1 (this (gt_mem_nhds εpos)) with ⟨δ, δ0, H⟩ exact ⟨δ, δ0, fun hx y hy h => (hf.edist_le hx hy).trans_lt (H h)⟩ -protected theorem continuousOn (hf : HoelderOnWith C r f s) (h0 : 0 < r) : ContinuousOn f s := +protected theorem continuousOn (hf : HolderOnWith C r f s) (h0 : 0 < r) : ContinuousOn f s := (hf.uniformContinuousOn h0).continuousOn -protected theorem mono (hf : HoelderOnWith C r f s) (ht : t ⊆ s) : HoelderOnWith C r f t := +protected theorem mono (hf : HolderOnWith C r f s) (ht : t ⊆ s) : HolderOnWith C r f t := fun _ hx _ hy => hf.edist_le (ht hx) (ht hy) -theorem ediam_image_le_of_le (hf : HoelderOnWith C r f s) {d : ℝ≥0∞} (hd : EMetric.diam s ≤ d) : +theorem ediam_image_le_of_le (hf : HolderOnWith C r f s) {d : ℝ≥0∞} (hd : EMetric.diam s ≤ d) : EMetric.diam (f '' s) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := EMetric.diam_image_le_iff.2 fun _ hx _ hy => hf.edist_le_of_le hx hy <| (EMetric.edist_le_diam_of_mem hx hy).trans hd -theorem ediam_image_le (hf : HoelderOnWith C r f s) : +theorem ediam_image_le (hf : HolderOnWith C r f s) : EMetric.diam (f '' s) ≤ (C : ℝ≥0∞) * EMetric.diam s ^ (r : ℝ) := hf.ediam_image_le_of_le le_rfl -theorem ediam_image_le_of_subset (hf : HoelderOnWith C r f s) (ht : t ⊆ s) : +theorem ediam_image_le_of_subset (hf : HolderOnWith C r f s) (ht : t ⊆ s) : EMetric.diam (f '' t) ≤ (C : ℝ≥0∞) * EMetric.diam t ^ (r : ℝ) := (hf.mono ht).ediam_image_le -theorem ediam_image_le_of_subset_of_le (hf : HoelderOnWith C r f s) (ht : t ⊆ s) {d : ℝ≥0∞} +theorem ediam_image_le_of_subset_of_le (hf : HolderOnWith C r f s) (ht : t ⊆ s) {d : ℝ≥0∞} (hd : EMetric.diam t ≤ d) : EMetric.diam (f '' t) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := (hf.mono ht).ediam_image_le_of_le hd -theorem ediam_image_inter_le_of_le (hf : HoelderOnWith C r f s) {d : ℝ≥0∞} +theorem ediam_image_inter_le_of_le (hf : HolderOnWith C r f s) {d : ℝ≥0∞} (hd : EMetric.diam t ≤ d) : EMetric.diam (f '' (t ∩ s)) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := hf.ediam_image_le_of_subset_of_le inter_subset_right <| (EMetric.diam_mono inter_subset_left).trans hd -theorem ediam_image_inter_le (hf : HoelderOnWith C r f s) (t : Set X) : +theorem ediam_image_inter_le (hf : HolderOnWith C r f s) (t : Set X) : EMetric.diam (f '' (t ∩ s)) ≤ (C : ℝ≥0∞) * EMetric.diam t ^ (r : ℝ) := hf.ediam_image_inter_le_of_le le_rfl -end HoelderOnWith +end HolderOnWith -namespace HoelderWith +namespace HolderWith variable {C r : ℝ≥0} {f : X → Y} -theorem edist_le (h : HoelderWith C r f) (x y : X) : +theorem edist_le (h : HolderWith C r f) (x y : X) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * edist x y ^ (r : ℝ) := h x y -theorem edist_le_of_le (h : HoelderWith C r f) {x y : X} {d : ℝ≥0∞} (hd : edist x y ≤ d) : +theorem edist_le_of_le (h : HolderWith C r f) {x y : X} {d : ℝ≥0∞} (hd : edist x y ≤ d) : edist (f x) (f y) ≤ (C : ℝ≥0∞) * d ^ (r : ℝ) := - (h.HoelderOnWith univ).edist_le_of_le trivial trivial hd + (h.holderOnWith univ).edist_le_of_le trivial trivial hd -theorem comp {Cg rg : ℝ≥0} {g : Y → Z} (hg : HoelderWith Cg rg g) {Cf rf : ℝ≥0} {f : X → Y} - (hf : HoelderWith Cf rf f) : HoelderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := - (hg.HoelderOnWith univ).comp_hoelderWith hf fun _ => trivial +theorem comp {Cg rg : ℝ≥0} {g : Y → Z} (hg : HolderWith Cg rg g) {Cf rf : ℝ≥0} {f : X → Y} + (hf : HolderWith Cf rf f) : HolderWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) := + (hg.holderOnWith univ).comp_holderWith hf fun _ => trivial -theorem comp_hoelderOnWith {Cg rg : ℝ≥0} {g : Y → Z} (hg : HoelderWith Cg rg g) {Cf rf : ℝ≥0} - {f : X → Y} {s : Set X} (hf : HoelderOnWith Cf rf f s) : - HoelderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := - (hg.HoelderOnWith univ).comp hf fun _ _ => trivial +theorem comp_holderOnWith {Cg rg : ℝ≥0} {g : Y → Z} (hg : HolderWith Cg rg g) {Cf rf : ℝ≥0} + {f : X → Y} {s : Set X} (hf : HolderOnWith Cf rf f s) : + HolderOnWith (Cg * Cf ^ (rg : ℝ)) (rg * rf) (g ∘ f) s := + (hg.holderOnWith univ).comp hf fun _ _ => trivial /-- A Hölder continuous function is uniformly continuous -/ -protected theorem uniformContinuous (hf : HoelderWith C r f) (h0 : 0 < r) : UniformContinuous f := - uniformContinuousOn_univ.mp <| (hf.HoelderOnWith univ).uniformContinuousOn h0 +protected theorem uniformContinuous (hf : HolderWith C r f) (h0 : 0 < r) : UniformContinuous f := + uniformContinuousOn_univ.mp <| (hf.holderOnWith univ).uniformContinuousOn h0 -protected theorem continuous (hf : HoelderWith C r f) (h0 : 0 < r) : Continuous f := +protected theorem continuous (hf : HolderWith C r f) (h0 : 0 < r) : Continuous f := (hf.uniformContinuous h0).continuous -theorem ediam_image_le (hf : HoelderWith C r f) (s : Set X) : +theorem ediam_image_le (hf : HolderWith C r f) (s : Set X) : EMetric.diam (f '' s) ≤ (C : ℝ≥0∞) * EMetric.diam s ^ (r : ℝ) := EMetric.diam_image_le_iff.2 fun _ hx _ hy => hf.edist_le_of_le <| EMetric.edist_le_diam_of_mem hx hy lemma const {y : Y} : - HoelderWith C r (Function.const X y) := fun x₁ x₂ => by + HolderWith C r (Function.const X y) := fun x₁ x₂ => by simp only [Function.const_apply, edist_self, zero_le] -lemma zero [Zero Y] : HoelderWith C r (0 : X → Y) := .const +lemma zero [Zero Y] : HolderWith C r (0 : X → Y) := .const -lemma of_isEmpty [IsEmpty X] : HoelderWith C r f := isEmptyElim +lemma of_isEmpty [IsEmpty X] : HolderWith C r f := isEmptyElim -lemma mono {C' : ℝ≥0} (hf : HoelderWith C r f) (h : C ≤ C') : - HoelderWith C' r f := +lemma mono {C' : ℝ≥0} (hf : HolderWith C r f) (h : C ≤ C') : + HolderWith C' r f := fun x₁ x₂ ↦ (hf x₁ x₂).trans (mul_right_mono (coe_le_coe.2 h)) -end HoelderWith +end HolderWith end Emetric @@ -211,30 +210,30 @@ section PseudoMetric variable [PseudoMetricSpace X] [PseudoMetricSpace Y] {C r : ℝ≥0} {f : X → Y} -namespace HoelderWith +namespace HolderWith -theorem nndist_le_of_le (hf : HoelderWith C r f) {x y : X} {d : ℝ≥0} (hd : nndist x y ≤ d) : +theorem nndist_le_of_le (hf : HolderWith C r f) {x y : X} {d : ℝ≥0} (hd : nndist x y ≤ d) : nndist (f x) (f y) ≤ C * d ^ (r : ℝ) := by rw [← ENNReal.coe_le_coe, ← edist_nndist, ENNReal.coe_mul, ENNReal.coe_rpow_of_nonneg _ r.coe_nonneg] apply hf.edist_le_of_le rwa [edist_nndist, ENNReal.coe_le_coe] -theorem nndist_le (hf : HoelderWith C r f) (x y : X) : +theorem nndist_le (hf : HolderWith C r f) (x y : X) : nndist (f x) (f y) ≤ C * nndist x y ^ (r : ℝ) := hf.nndist_le_of_le le_rfl -theorem dist_le_of_le (hf : HoelderWith C r f) {x y : X} {d : ℝ} (hd : dist x y ≤ d) : +theorem dist_le_of_le (hf : HolderWith C r f) {x y : X} {d : ℝ} (hd : dist x y ≤ d) : dist (f x) (f y) ≤ C * d ^ (r : ℝ) := by lift d to ℝ≥0 using dist_nonneg.trans hd rw [dist_nndist] at hd ⊢ norm_cast at hd ⊢ exact hf.nndist_le_of_le hd -theorem dist_le (hf : HoelderWith C r f) (x y : X) : dist (f x) (f y) ≤ C * dist x y ^ (r : ℝ) := +theorem dist_le (hf : HolderWith C r f) (x y : X) : dist (f x) (f y) ≤ C * dist x y ^ (r : ℝ) := hf.dist_le_of_le le_rfl -end HoelderWith +end HolderWith end PseudoMetric @@ -243,7 +242,7 @@ section Metric variable [PseudoMetricSpace X] [MetricSpace Y] {C r : ℝ≥0} {f : X → Y} @[simp] -lemma hoelderWith_zero_iff : HoelderWith 0 r f ↔ ∀ x₁ x₂, f x₁ = f x₂ := by +lemma holderWith_zero_iff : HolderWith 0 r f ↔ ∀ x₁ x₂, f x₁ = f x₂ := by refine ⟨fun h x₁ x₂ => ?_, fun h x₁ x₂ => h x₁ x₂ ▸ ?_⟩ · specialize h x₁ x₂ simp [ENNReal.coe_zero, zero_mul, nonpos_iff_eq_zero, edist_eq_zero] at h @@ -256,20 +255,20 @@ section SeminormedAddCommGroup variable [PseudoMetricSpace X] [SeminormedAddCommGroup Y] {C C' r : ℝ≥0} {f g : X → Y} -namespace HoelderWith +namespace HolderWith -lemma add (hf : HoelderWith C r f) (hg : HoelderWith C' r g) : - HoelderWith (C + C') r (f + g) := fun x₁ x₂ => by +lemma add (hf : HolderWith C r f) (hg : HolderWith C' r g) : + HolderWith (C + C') r (f + g) := fun x₁ x₂ => by refine le_trans (edist_add_add_le _ _ _ _) <| le_trans (add_le_add (hf x₁ x₂) (hg x₁ x₂)) ?_ rw [coe_add, add_mul] lemma smul {α} [NormedDivisionRing α] [Module α Y] [BoundedSMul α Y] (a : α) - (hf : HoelderWith C r f) : HoelderWith (C * ‖a‖₊) r (a • f) := fun x₁ x₂ => by + (hf : HolderWith C r f) : HolderWith (C * ‖a‖₊) r (a • f) := fun x₁ x₂ => by rw [Pi.smul_apply, coe_mul, Pi.smul_apply, edist_smul₀, mul_comm (C : ℝ≥0∞), ENNReal.smul_def, smul_eq_mul, mul_assoc] gcongr exact hf x₁ x₂ -end HoelderWith +end HolderWith end SeminormedAddCommGroup diff --git a/docs/overview.yaml b/docs/overview.yaml index 1c28518967b6a..be28612dbf810 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -247,7 +247,7 @@ Topology: sequential compactness is equivalent to compactness (Bolzano-Weierstrass): 'UniformSpace.isCompact_iff_isSeqCompact' Heine-Borel theorem (proper metric space version): 'Metric.isCompact_iff_isClosed_bounded' Lipschitz continuity: 'LipschitzWith' - Hölder continuity: 'HoelderWith' + Hölder continuity: 'HolderWith' contraction mapping theorem: 'ContractingWith.exists_fixedPoint' Baire theorem: 'dense_iInter_of_isOpen' Arzela-Ascoli theorem: 'BoundedContinuousFunction.arzela_ascoli' diff --git a/docs/undergrad.yaml b/docs/undergrad.yaml index 0ed700ef27967..21619980559e5 100644 --- a/docs/undergrad.yaml +++ b/docs/undergrad.yaml @@ -517,7 +517,7 @@ Measures and integral calculus: differentiability of integrals with respect to parameters: '' $\mathrm{L}^p$ spaces where $1 ≤ p ≤ ∞$: 'MeasureTheory.Lp' Completeness of $\mathrm{L}^p$ spaces: 'MeasureTheory.Lp.instCompleteSpace' - Hölder's inequality: 'NNReal.lintegral_mul_le_Lp_mul_Lq' + Holder's inequality: 'NNReal.lintegral_mul_le_Lp_mul_Lq' Fubini's theorem: 'MeasureTheory.integral_prod' change of variables for multiple integrals: 'MeasureTheory.integral_image_eq_integral_abs_det_fderiv_smul' change of variables to polar co-ordinates: 'integral_comp_polarCoord_symm' diff --git a/scripts/nolints.json b/scripts/nolints.json index d4e5bb4d35641..197243db4c7e0 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -193,8 +193,8 @@ ["docBlame", "Isocrystal.«term_≃ᶠⁱ[_,_]_»"], ["docBlame", "Isocrystal.«termΦ(_,_)»"], ["docBlame", "Isocrystal.«termφ(_,_)»"], - ["docBlame", "JordanHoelderLattice.IsMaximal"], - ["docBlame", "JordanHoelderLattice.Iso"], + ["docBlame", "JordanHolderLattice.IsMaximal"], + ["docBlame", "JordanHolderLattice.Iso"], ["docBlame", "Kronecker.«term_⊗ₖ_»"], ["docBlame", "Kronecker.«term_⊗ₖₜ[_]_»"], ["docBlame", "Kronecker.«term_⊗ₖₜ_»"], From 85cefec280e7ac8712b13702af7d67f71cbedfad Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Fri, 20 Sep 2024 01:19:01 +0000 Subject: [PATCH 060/170] chore(Data/Finset): change nonempty_cons to cons_nonempty (#16952) In analogy with insert_nonempty (and other Finset nonempty lemmata), this should be named `cons_nonempty` rather than `nonempty_cons`. --- Mathlib/Data/Finset/Basic.lean | 6 ++++-- Mathlib/Data/Finset/Lattice.lean | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index 42f71fe948687..4be4579898b91 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -773,9 +773,11 @@ theorem mk_cons {s : Multiset α} (h : (a ::ₘ s).Nodup) : theorem cons_empty (a : α) : cons a ∅ (not_mem_empty _) = {a} := rfl @[simp, aesop safe apply (rule_sets := [finsetNonempty])] -theorem nonempty_cons (h : a ∉ s) : (cons a s h).Nonempty := +theorem cons_nonempty (h : a ∉ s) : (cons a s h).Nonempty := ⟨a, mem_cons.2 <| Or.inl rfl⟩ +@[deprecated (since := "2024-09-19")] alias nonempty_cons := cons_nonempty + @[simp] theorem nonempty_mk {m : Multiset α} {hm} : (⟨m, hm⟩ : Finset α).Nonempty ↔ m ≠ 0 := by induction m using Multiset.induction_on <;> simp @@ -1098,7 +1100,7 @@ obtained by inserting an element in `t`. -/ @[elab_as_elim] theorem Nonempty.cons_induction {α : Type*} {p : ∀ s : Finset α, s.Nonempty → Prop} (singleton : ∀ a, p {a} (singleton_nonempty _)) - (cons : ∀ a s (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (nonempty_cons h)) + (cons : ∀ a s (h : a ∉ s) (hs), p s hs → p (Finset.cons a s h) (cons_nonempty h)) {s : Finset α} (hs : s.Nonempty) : p s hs := by induction s using Finset.cons_induction with | empty => exact (not_nonempty_empty hs).elim diff --git a/Mathlib/Data/Finset/Lattice.lean b/Mathlib/Data/Finset/Lattice.lean index d577bf61dda82..cc7f493f2efbc 100644 --- a/Mathlib/Data/Finset/Lattice.lean +++ b/Mathlib/Data/Finset/Lattice.lean @@ -704,7 +704,7 @@ theorem coe_sup' : ((s.sup' H f : α) : WithBot α) = s.sup ((↑) ∘ f) := by @[simp] theorem sup'_cons {b : β} {hb : b ∉ s} : - (cons b s hb).sup' (nonempty_cons hb) f = f b ⊔ s.sup' H f := by + (cons b s hb).sup' (cons_nonempty hb) f = f b ⊔ s.sup' H f := by rw [← WithBot.coe_eq_coe] simp [WithBot.coe_sup] @@ -873,7 +873,7 @@ theorem coe_inf' : ((s.inf' H f : α) : WithTop α) = s.inf ((↑) ∘ f) := @[simp] theorem inf'_cons {b : β} {hb : b ∉ s} : - (cons b s hb).inf' (nonempty_cons hb) f = f b ⊓ s.inf' H f := + (cons b s hb).inf' (cons_nonempty hb) f = f b ⊓ s.inf' H f := @sup'_cons αᵒᵈ _ _ _ H f _ _ @[simp] From c01cdb497c2bc9b5171b48c33289f659943666e6 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 20 Sep 2024 02:10:14 +0000 Subject: [PATCH 061/170] chore: use List.eraseDups in simps (#16234) --- Mathlib/Combinatorics/Quiver/Path.lean | 1 + Mathlib/Data/List/EditDistance/Defs.lean | 1 + Mathlib/Tactic/Simps/Basic.lean | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Mathlib/Combinatorics/Quiver/Path.lean b/Mathlib/Combinatorics/Quiver/Path.lean index 5466770a184d0..08cf1779430aa 100644 --- a/Mathlib/Combinatorics/Quiver/Path.lean +++ b/Mathlib/Combinatorics/Quiver/Path.lean @@ -5,6 +5,7 @@ Authors: David Wärn, Scott Morrison -/ import Mathlib.Combinatorics.Quiver.Basic import Mathlib.Logic.Lemmas +import Batteries.Data.List.Basic /-! # Paths in quivers diff --git a/Mathlib/Data/List/EditDistance/Defs.lean b/Mathlib/Data/List/EditDistance/Defs.lean index ed13538ca6e25..2c9b6ab2d89f8 100644 --- a/Mathlib/Data/List/EditDistance/Defs.lean +++ b/Mathlib/Data/List/EditDistance/Defs.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Liesinger -/ import Mathlib.Algebra.Group.Defs +import Batteries.Data.List.Basic /-! # Levenshtein distances diff --git a/Mathlib/Tactic/Simps/Basic.lean b/Mathlib/Tactic/Simps/Basic.lean index 9d7dfe3ba1c6e..1caba0e4825ab 100644 --- a/Mathlib/Tactic/Simps/Basic.lean +++ b/Mathlib/Tactic/Simps/Basic.lean @@ -8,7 +8,6 @@ import Lean.Elab.App import Mathlib.Tactic.Simps.NotationClass import Batteries.Data.String.Basic import Mathlib.Lean.Expr.Basic -import Batteries.Data.List.Basic /-! # Simps attribute @@ -1180,7 +1179,7 @@ def simpsTac (ref : Syntax) (nm : Name) (cfg : Config := {}) let env ← getEnv let some d := env.find? nm | throwError "Declaration {nm} doesn't exist." let lhs : Expr := mkConst d.name <| d.levelParams.map Level.param - let todo := todo.pwFilter (·.1 ≠ ·.1) |>.map fun (proj, stx) ↦ (proj ++ "_", stx) + let todo := todo.eraseDups |>.map fun (proj, stx) ↦ (proj ++ "_", stx) let mut cfg := cfg MetaM.run' <| addProjections ref d.levelParams nm d.type lhs (d.value?.getD default) #[] (mustBeStr := true) cfg todo [] From 94db6790ed4386dedf3c49c0a27e6be2864fcc50 Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Fri, 20 Sep 2024 03:09:41 +0000 Subject: [PATCH 062/170] feat(Topology/UniformSpace): `Subtype.isComplete_iff` (#16730) In the style of `Subtype.isCompact_iff` Co-authored-by: Yakov Pechersky --- .../Topology/UniformSpace/UniformEmbedding.lean | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean index a543aabffffb7..ed90ccfc3618a 100644 --- a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean +++ b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean @@ -265,6 +265,21 @@ theorem isComplete_image_iff {m : α → β} {s : Set α} (hm : UniformInducing simp_rw [IsComplete, imp.swap (a := Cauchy _), ← mem_Iic (b := 𝓟 _), fact1.forall fact2, hm.cauchy_map_iff, exists_mem_image, map_le_iff_le_comap, hm.inducing.nhds_eq_comap] +/-- If `f : X → Y` is an `UniformInducing` map, the image `f '' s` of a set `s` is complete + if and only if `s` is complete. -/ +theorem UniformInducing.isComplete_iff {f : α → β} {s : Set α} (hf : UniformInducing f) : + IsComplete (f '' s) ↔ IsComplete s := isComplete_image_iff hf + +/-- If `f : X → Y` is an `UniformEmbedding`, the image `f '' s` of a set `s` is complete + if and only if `s` is complete. -/ +theorem UniformEmbedding.isComplete_iff {f : α → β} {s : Set α} (hf : UniformEmbedding f) : + IsComplete (f '' s) ↔ IsComplete s := hf.toUniformInducing.isComplete_iff + +/-- Sets of a subtype are complete iff their image under the coercion is complete. -/ +theorem Subtype.isComplete_iff {p : α → Prop} {s : Set { x // p x }} : + IsComplete s ↔ IsComplete ((↑) '' s : Set α) := + uniformEmbedding_subtype_val.isComplete_iff.symm + alias ⟨isComplete_of_complete_image, _⟩ := isComplete_image_iff theorem completeSpace_iff_isComplete_range {f : α → β} (hf : UniformInducing f) : From 6dcd0d943385f315b956fc76968c842a3ad4072c Mon Sep 17 00:00:00 2001 From: thorimur <68410468+thorimur@users.noreply.github.com> Date: Fri, 20 Sep 2024 03:37:39 +0000 Subject: [PATCH 063/170] feat: `tfae_have ... :=` syntax (#10653) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR refactors `tfae_have` in terms of `have`, thus supporting all the syntax that `have` supports. We can now also write: ```lean example : TFAE [P, Q, R] := by tfae_have 1 → 2 := sorry tfae_have 2 → 1 | p => f p tfae_have ⟨mp, mpr⟩ : 2 ↔ 3 := sorry ... ``` Previously, `tfae_have` exclusively pushed a new goal to the top of the goal list, requiring that the result be proved via tactic. This PR does not deprecate or remove the "old-style" syntax, but does de-document it. The removal of old-style syntax is done in #11000. This tees us up for a `tfae` block tactic (#10991, #11003). See [Zulip](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/tfae_have.201.20.E2.86.92.202.20.3A.3D.20syntax). Co-authored-by: Yury G. Kudryashov --- Mathlib/Tactic/TFAE.lean | 253 +++++++++++++++++++++++++++------------ scripts/noshake.json | 2 +- test/tfae.lean | 45 +++++++ 3 files changed, 224 insertions(+), 76 deletions(-) diff --git a/Mathlib/Tactic/TFAE.lean b/Mathlib/Tactic/TFAE.lean index 6eaad297bad50..2a4ec7918e278 100644 --- a/Mathlib/Tactic/TFAE.lean +++ b/Mathlib/Tactic/TFAE.lean @@ -15,48 +15,108 @@ This file provides the tactics `tfae_have` and `tfae_finish` for proving goals o `TFAE [P₁, P₂, ...]`. -/ -open List Lean Meta Expr Elab.Term Elab.Tactic Mathlib.Tactic Qq - namespace Mathlib.Tactic.TFAE -/-- An arrow of the form `←`, `→`, or `↔`. -/ -syntax impArrow := " → " <|> " ↔ " <|> " ← " +/-! # Parsing and syntax + +We implement `tfae_have` in terms of a syntactic `have`. To support as much of the same syntax as +possible, we recreate the parsers for `have`, except with the changes necessary for `tfae_have`. +-/ + +open Lean.Parser Term + +namespace Parser + +/- An arrow of the form `←`, `→`, or `↔`. -/ +private def impTo : Parser := leading_parser unicodeSymbol " → " " -> " +private def impFrom : Parser := leading_parser unicodeSymbol " ← " " <- " +private def impIff : Parser := leading_parser unicodeSymbol " ↔ " " <-> " +private def impArrow : Parser := leading_parser impTo <|> impFrom <|> impIff + +/-- A `tfae_have` type specification, e.g. `1 ↔ 3` The numbers refer to the proposition at the +corresponding position in the `TFAE` goal (starting at 1). -/ +private def tfaeType := leading_parser num >> impArrow >> num + +/-! +The following parsers are similar to those for `have` in `Lean.Parser.Term`, but +instead of `optType`, we use `tfaeType := num >> impArrow >> num` (as a `tfae_have` invocation must +always include this specification). Also, we disallow including extra binders, as that makes no +sense in this context; we also include `" : "` after the binder to avoid breaking `tfae_have 1 → 2` +syntax (which, unlike `have`, omits `" : "`). +-/ + +/- See `haveIdLhs`. + +We omit `many (ppSpace >> letIdBinder)`, as it makes no sense to add extra arguments to a +`tfae_have` decl. -/ +private def tfaeHaveIdLhs := leading_parser + ((ppSpace >> binderIdent >> " : ") <|> hygieneInfo) >> tfaeType +/- See `haveIdDecl`. E.g. `h : 1 → 3 := term`. -/ +private def tfaeHaveIdDecl := leading_parser (withAnonymousAntiquot := false) + atomic (tfaeHaveIdLhs >> " := ") >> termParser +/- See `haveEqnsDecl`. E.g. `h : 1 → 3 | p => f p`. -/ +private def tfaeHaveEqnsDecl := leading_parser (withAnonymousAntiquot := false) + tfaeHaveIdLhs >> matchAlts +/- See `letPatDecl`. E.g. `⟨mp, mpr⟩ : 1 ↔ 3 := term`. -/ +private def tfaeHavePatDecl := leading_parser (withAnonymousAntiquot := false) + atomic (termParser >> pushNone >> " : " >> tfaeType >> " := ") >> termParser +/- See `haveDecl`. Any of `tfaeHaveIdDecl`, `tfaeHavePatDecl`, or `tfaeHaveEqnsDecl`. -/ +private def tfaeHaveDecl := leading_parser (withAnonymousAntiquot := false) + tfaeHaveIdDecl <|> (ppSpace >> tfaeHavePatDecl) <|> tfaeHaveEqnsDecl + +end Parser + +open Parser /-- `tfae_have` introduces hypotheses for proving goals of the form `TFAE [P₁, P₂, ...]`. Specifically, -`tfae_have i arrow j` introduces a hypothesis of type `Pᵢ arrow Pⱼ` to the local context, -where `arrow` can be `→`, `←`, or `↔`. Note that `i` and `j` are natural number indices (beginning -at 1) used to specify the propositions `P₁, P₂, ...` that appear in the `TFAE` goal list. A proof -is required afterward, typically via a tactic block. +`tfae_have i j := ...` introduces a hypothesis of type `Pᵢ Pⱼ` to the local +context, where `` can be `→`, `←`, or `↔`. Note that `i` and `j` are natural number indices +(beginning at 1) used to specify the propositions `P₁, P₂, ...` that appear in the goal. ```lean example (h : P → R) : TFAE [P, Q, R] := by - tfae_have 1 → 3 - · exact h + tfae_have 1 → 3 := h ... ``` The resulting context now includes `tfae_1_to_3 : P → R`. -The introduced hypothesis can be given a custom name, in analogy to `have` syntax: +Once sufficient hypotheses have been introduced by `tfae_have`, `tfae_finish` can be used to close +the goal. For example, + ```lean -tfae_have h : 2 ↔ 3 +example : TFAE [P, Q, R] := by + tfae_have 1 → 2 := sorry /- proof of P → Q -/ + tfae_have 2 → 1 := sorry /- proof of Q → P -/ + tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/ + tfae_finish ``` -Once sufficient hypotheses have been introduced by `tfae_have`, `tfae_finish` can be used to close -the goal. +All relevant features of `have` are supported by `tfae_have`, including naming, destructuring, goal +creation, and matching. These are demonstrated below. ```lean -example : TFAE [P, Q, R] := by +example : TFAE [P, Q] := by + -- `tfae_1_to_2 : P → Q`: + tfae_have 1 → 2 := sorry + -- `hpq : P → Q`: + tfae_have hpq : 1 → 2 := sorry + -- inaccessible `h✝ : P → Q`: + tfae_have _ : 1 → 2 := sorry + -- `tfae_1_to_2 : P → Q`, and `?a` is a new goal: + tfae_have 1 → 2 := f ?a + -- create a goal of type `P → Q`: tfae_have 1 → 2 - · /- proof of P → Q -/ - tfae_have 2 → 1 - · /- proof of Q → P -/ - tfae_have 2 ↔ 3 - · /- proof of Q ↔ R -/ - tfae_finish + · exact (sorry : P → Q) + -- match on `p : P` and prove `Q`: + tfae_have 1 → 2 + | p => f p + -- introduces `pq : P → Q`, `qp : Q → P`: + tfae_have ⟨pq, qp⟩ : 1 ↔ 2 := sorry + ... ``` -/ -syntax (name := tfaeHave) "tfae_have " (ident " : ")? num impArrow num : tactic +syntax (name := tfaeHave) "tfae_have " tfaeHaveDecl : tactic /-- `tfae_finish` is used to close goals of the form `TFAE [P₁, P₂, ...]` once a sufficient collection @@ -67,19 +127,19 @@ of hypotheses of the form `Pᵢ → Pⱼ` or `Pᵢ ↔ Pⱼ` have been introduce Example: ```lean example : TFAE [P, Q, R] := by - tfae_have 1 → 2 - · /- proof of P → Q -/ - tfae_have 2 → 1 - · /- proof of Q → P -/ - tfae_have 2 ↔ 3 - · /- proof of Q ↔ R -/ + tfae_have 1 → 2 := sorry /- proof of P → Q -/ + tfae_have 2 → 1 := sorry /- proof of Q → P -/ + tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/ tfae_finish ``` -/ syntax (name := tfaeFinish) "tfae_finish" : tactic + /-! # Setup -/ +open List Lean Meta Expr Elab Tactic Mathlib.Tactic Qq + /-- Extract a list of `Prop` expressions from an expression of the form `TFAE [P₁, P₂, ...]` as long as `[P₁, P₂, ...]` is an explicit list. -/ partial def getTFAEList (t : Expr) : MetaM (Q(List Prop) × List Q(Prop)) := do @@ -159,62 +219,72 @@ def proveTFAE (is : List ℕ) (l : Q(List Prop)) : MetaM Q(TFAE $l) := do /-! # `tfae_have` components -/ /-- Construct a name for a hypothesis introduced by `tfae_have`. -/ -def mkTFAEHypName (i j : TSyntax `num) (arr : TSyntax ``impArrow) : MetaM Name := do - let arr ← match arr with - | `(impArrow| ← ) => pure "from" - | `(impArrow| → ) => pure "to" - | `(impArrow| ↔ ) => pure "iff" - | _ => throwErrorAt arr "expected '←', '→', or '↔'" - return .mkSimple <| String.intercalate "_" ["tfae", s!"{i.getNat}", arr, s!"{j.getNat}"] - -open Elab in -/-- The core of `tfae_have`, which behaves like `haveLetCore` in `Mathlib.Tactic.Have`. -/ -def tfaeHaveCore (goal : MVarId) (name : Option (TSyntax `ident)) (i j : TSyntax `num) - (arrow : TSyntax ``impArrow) (t : Expr) : TermElabM (MVarId × MVarId) := - goal.withContext do - let n := (Syntax.getId <$> name).getD <|← mkTFAEHypName i j arrow - let (goal1, t, p) ← do - let p ← mkFreshExprMVar t MetavarKind.syntheticOpaque n - pure (p.mvarId!, t, p) - let (fv, goal2) ← (← MVarId.assert goal n t p).intro1P - if let some stx := name then - goal2.withContext do - Term.addTermInfo' (isBinder := true) stx (mkFVar fv) - pure (goal1, goal2) +def mkTFAEId : TSyntax ``tfaeType → MacroM Name + | `(tfaeType|$i:num $arr:impArrow $j:num) => do + let arr ← match arr with + | `(impArrow| ← ) => pure "from" + | `(impArrow| → ) => pure "to" + | `(impArrow| ↔ ) => pure "iff" + | _ => Macro.throwUnsupported + return .mkSimple <| String.intercalate "_" ["tfae", s!"{i.getNat}", arr, s!"{j.getNat}"] + | _ => Macro.throwUnsupported /-- Turn syntax for a given index into a natural number, as long as it lies between `1` and `maxIndex`. -/ -def elabIndex (i : TSyntax `num) (maxIndex : ℕ) : TacticM ℕ := do +def elabIndex (i : TSyntax `num) (maxIndex : ℕ) : MetaM ℕ := do let i' := i.getNat - unless Nat.ble 1 i' && Nat.ble i' maxIndex do - throwError "{i} must be between 1 and {maxIndex}" + unless 1 ≤ i' && i' ≤ maxIndex do + throwErrorAt i "{i} must be between 1 and {maxIndex}" return i' -/-- Construct an expression for the type `Pj → Pi`, `Pi → Pj`, or `Pi ↔ Pj` given expressions -`Pi Pj : Q(Prop)` and `impArrow` syntax `arr`, depending on whether `arr` is `←`, `→`, or `↔` -respectively. -/ -def mkImplType (Pi : Q(Prop)) (arr : TSyntax ``impArrow) (Pj : Q(Prop)) : MetaM Q(Prop) := do - match arr with - | `(impArrow| ← ) => pure q($Pj → $Pi) - | `(impArrow| → ) => pure q($Pi → $Pj) - | `(impArrow| ↔ ) => pure q($Pi ↔ $Pj) - | _ => throwErrorAt arr "expected '←', '→', or '↔'" - /-! # Tactic implementation -/ -elab_rules : tactic -| `(tactic| tfae_have $[$h:ident : ]? $i:num $arr:impArrow $j:num) => do - let goal ← getMainGoal - goal.withContext do - let (_, tfaeList) ← getTFAEList (← goal.getType) - let l₀ := tfaeList.length - let i' ← elabIndex i l₀ - let j' ← elabIndex j l₀ +/-- Accesses the propositions at indices `i` and `j` of `tfaeList`, and constructs the expression +`Pi Pj`, which will be the type of our `tfae_have` hypothesis -/ +def elabTFAEType (tfaeList : List Q(Prop)) : TSyntax ``tfaeType → TermElabM Expr + | stx@`(tfaeType|$i:num $arr:impArrow $j:num) => do + let l := tfaeList.length + let i' ← elabIndex i l + let j' ← elabIndex j l let Pi := tfaeList.get! (i'-1) let Pj := tfaeList.get! (j'-1) - let type ← mkImplType Pi arr Pj - let (goal1, goal2) ← tfaeHaveCore goal h i j arr type - replaceMainGoal [goal1, goal2] + Term.addTermInfo' i Pi q(Prop) + Term.addTermInfo' j Pj q(Prop) + match arr with + | `(impArrow| ← ) => Term.addTermInfo stx q($Pj → $Pi) q(Prop) + | `(impArrow| → ) => Term.addTermInfo stx q($Pi → $Pj) q(Prop) + | `(impArrow| ↔ ) => Term.addTermInfo stx q($Pi ↔ $Pj) q(Prop) + | _ => throwUnsupportedSyntax + | _ => throwUnsupportedSyntax + +/- Convert `tfae_have i j ...` to `tfae_have tfae_i_arr_j : i j ...`. See +`expandHave`, which is responsible for inserting `this` in `have : A := ...`. -/ +macro_rules +| `(tfaeHave|tfae_have $hy:hygieneInfo $t:tfaeType := $val) => do + let id := HygieneInfo.mkIdent hy (← mkTFAEId t) (canonical := true) + `(tfaeHave|tfae_have $id : $t := $val) +| `(tfaeHave|tfae_have $hy:hygieneInfo $t:tfaeType $alts:matchAlts) => do + let id := HygieneInfo.mkIdent hy (← mkTFAEId t) (canonical := true) + `(tfaeHave|tfae_have $id : $t $alts) + +open Term + +elab_rules : tactic +| `(tfaeHave|tfae_have $d:tfaeHaveDecl) => withMainContext do + let goal ← getMainGoal + let (_, tfaeList) ← getTFAEList (← goal.getType) + withRef d do + match d with + | `(tfaeHaveDecl| $b : $t:tfaeType := $pf:term) => + let type ← elabTFAEType tfaeList t + evalTactic <|← `(tactic|have $b : $(← exprToSyntax type) := $pf) + | `(tfaeHaveDecl| $b : $t:tfaeType $alts:matchAlts) => + let type ← elabTFAEType tfaeList t + evalTactic <|← `(tactic|have $b : $(← exprToSyntax type) $alts:matchAlts) + | `(tfaeHaveDecl| $pat:term : $t:tfaeType := $pf:term) => + let type ← elabTFAEType tfaeList t + evalTactic <|← `(tactic|have $pat:term : $(← exprToSyntax type) := $pf) + | _ => throwUnsupportedSyntax elab_rules : tactic | `(tactic| tfae_finish) => do @@ -225,7 +295,7 @@ elab_rules : tactic let is ← tfaeList.mapM AtomM.addAtom let mut hyps := #[] for hyp in ← getLocalHyps do - let ty ← inferType hyp + let ty ← whnfR <|← instantiateMVars <|← inferType hyp if let (``Iff, #[p1, p2]) := ty.getAppFnArgs then let q1 ← AtomM.addAtom p1 let q2 ← AtomM.addAtom p2 @@ -237,6 +307,39 @@ elab_rules : tactic hyps := hyps.push (q1, q2, hyp) proveTFAE hyps (← get).atoms is tfaeListQ +/-! + +# "Old-style" `tfae_have` + +We preserve the "old-style" `tfae_have` (which behaves like Mathlib `have`) for compatibility +purposes. + +-/ + +@[inherit_doc tfaeHave] +syntax (name := tfaeHave') "tfae_have " tfaeHaveIdLhs : tactic + +macro_rules +| `(tfaeHave'|tfae_have $hy:hygieneInfo $t:tfaeType) => do + let id := HygieneInfo.mkIdent hy (← mkTFAEId t) (canonical := true) + `(tfaeHave'|tfae_have $id : $t) + +elab_rules : tactic +| `(tfaeHave'|tfae_have $d:tfaeHaveIdLhs) => withMainContext do + let goal ← getMainGoal + let (_, tfaeList) ← getTFAEList (← goal.getType) + -- Note that due to the macro above, the following match is exhaustive. + match d with + | `(tfaeHaveIdLhs| $b:ident : $t:tfaeType) => + let n := b.getId + let type ← elabTFAEType tfaeList t + let p ← mkFreshExprMVar type MetavarKind.syntheticOpaque n + let (fv, mainGoal) ← (← MVarId.assert goal n type p).intro1P + mainGoal.withContext do + Term.addTermInfo' (isBinder := true) b (mkFVar fv) + replaceMainGoal [p.mvarId!, mainGoal] + | _ => throwUnsupportedSyntax + end TFAE end Mathlib.Tactic diff --git a/scripts/noshake.json b/scripts/noshake.json index 9360cd39d6f6e..f89111e03b279 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -211,7 +211,7 @@ "Mathlib.Tactic.Use": ["Batteries.Logic"], "Mathlib.Tactic.TermCongr": ["Mathlib.Logic.Basic"], "Mathlib.Tactic.Tauto": ["Mathlib.Logic.Basic"], - "Mathlib.Tactic.TFAE": ["Mathlib.Data.List.TFAE"], + "Mathlib.Tactic.TFAE": ["Mathlib.Data.List.TFAE", "Mathlib.Tactic.Have"], "Mathlib.Tactic.Subsingleton": ["Mathlib.Logic.Basic", "Std.Logic"], "Mathlib.Tactic.ReduceModChar": ["Mathlib.Data.ZMod.Basic", "Mathlib.RingTheory.Polynomial.Basic"], diff --git a/test/tfae.lean b/test/tfae.lean index 71bab17d358db..677908af74af9 100644 --- a/test/tfae.lean +++ b/test/tfae.lean @@ -1,4 +1,5 @@ import Mathlib.Tactic.TFAE +import Mathlib.Tactic.SuccessIfFailWithMsg open List set_option autoImplicit true @@ -121,3 +122,47 @@ example (h₁ : P → Q) (h₂ : Q → P) : TFAE [P, Q] := by tfae_finish end context + +section term + +axiom P : Prop +axiom Q : Prop +axiom pq : P → Q +axiom qp : Q → P + +example : TFAE [P, Q] := by + tfae_have h : 1 → 2 := pq + guard_hyp h : P → Q + tfae_have _ : 1 ← 2 := qp + tfae_finish + +example : TFAE [P, Q] := by + have n : ℕ := 4 + tfae_have 1 → 2 := by + guard_hyp n : ℕ -- hypotheses are accessible (context is correct) + guard_target =ₛ P → Q -- expected type is known + exact pq + tfae_have 1 ← 2 := qp + tfae_finish + +example : TFAE [P, Q] := by + have n : ℕ := 3 + tfae_have 2 ← 1 := fun p => ?Qgoal + case Qgoal => exact pq p + refine ?a + fail_if_success (tfae_have 1 ← 2 := ((?a).out 1 2 sorry sorry).mpr) + tfae_have 2 → 1 := qp + tfae_finish + +example : TFAE [P, Q] := by + tfae_have 1 → 2 + | p => pq p + tfae_have 2 → 1 + | q => qp q + tfae_finish + +example : TFAE [P, Q] := by + tfae_have ⟨mp, mpr⟩ : 1 ↔ 2 := ⟨pq, qp⟩ + tfae_finish + +end term From 33b95b3e8b1593c67e03565adbc04b323e2437a4 Mon Sep 17 00:00:00 2001 From: Etienne Date: Fri, 20 Sep 2024 08:39:38 +0000 Subject: [PATCH 064/170] feat: a measurable cylinder is measurable (#16939) Add this easy lemma. --- Mathlib/MeasureTheory/Constructions/Cylinders.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/MeasureTheory/Constructions/Cylinders.lean b/Mathlib/MeasureTheory/Constructions/Cylinders.lean index 381a125b81a96..3ef19d096a73e 100644 --- a/Mathlib/MeasureTheory/Constructions/Cylinders.lean +++ b/Mathlib/MeasureTheory/Constructions/Cylinders.lean @@ -272,6 +272,12 @@ theorem mem_measurableCylinders (t : Set (∀ i, α i)) : t ∈ measurableCylinders α ↔ ∃ s S, MeasurableSet S ∧ t = cylinder s S := by simp_rw [measurableCylinders, mem_iUnion, exists_prop, mem_singleton_iff] +@[measurability] +theorem _root_.MeasurableSet.of_mem_measurableCylinders {s : Set (Π i, α i)} + (hs : s ∈ measurableCylinders α) : MeasurableSet s := by + obtain ⟨I, t, mt, rfl⟩ := (mem_measurableCylinders s).1 hs + exact mt.cylinder + /-- A finset `s` such that `t = cylinder s S`. `S` is given by `measurableCylinders.set`. -/ noncomputable def measurableCylinders.finset (ht : t ∈ measurableCylinders α) : Finset ι := ((mem_measurableCylinders t).mp ht).choose From a2208a9f788d8e5bd5e09bba120600a2eccf7e35 Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Fri, 20 Sep 2024 11:49:27 +0000 Subject: [PATCH 065/170] chore: pi_bounds cleanup, add mathematica script (#16930) * Rewrites the `pi_(lower|upper)_bound` tactics to allow some more general input * Clean up outdated porting notes * Add a mathematica script so people can go further if they want * Rename the pi bound theorems to have names like `pi_gt_d6` since the existing names do not scale well * `pi_gt_314` -> `pi_gt_d2` * `pi_lt_315` -> `pi_lt_d2` * `pi_gt_31415` -> `pi_gt_d4` * `pi_lt_31416` -> `pi_lt_d4` * `pi_gt_3141592` -> `pi_gt_d6` * `pi_lt_3141593` -> `pi_lt_d6` * Add a 20-digit calculation of pi [on request](https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/Code.20to.20generate.20the.20pi.20bound.20witnesses/near/470184223) since this file is not slow anymore Co-authored-by: Mario Carneiro Co-authored-by: Mario Carneiro --- Mathlib/Data/Real/Pi/Bounds.lean | 209 +++++++++++++++++++------------ 1 file changed, 127 insertions(+), 82 deletions(-) diff --git a/Mathlib/Data/Real/Pi/Bounds.lean b/Mathlib/Data/Real/Pi/Bounds.lean index 20ca11d6273d2..53573cbcf7b0b 100644 --- a/Mathlib/Data/Real/Pi/Bounds.lean +++ b/Mathlib/Data/Real/Pi/Bounds.lean @@ -11,34 +11,29 @@ import Mathlib.Analysis.SpecialFunctions.Trigonometric.Bounds This file contains lemmas which establish bounds on `Real.pi`. Notably, these include `pi_gt_sqrtTwoAddSeries` and `pi_lt_sqrtTwoAddSeries`, which bound `π` using series; -numerical bounds on `π` such as `pi_gt_314`and `pi_lt_315` (more precise versions are given, too). +numerical bounds on `π` such as `pi_gt_d2` and `pi_lt_d2` (more precise versions are given, too). See also `Mathlib/Data/Real/Pi/Leibniz.lean` and `Mathlib/Data/Real/Pi/Wallis.lean` for infinite formulas for `π`. -/ --- Porting note: needed to add a lot of type ascriptions for lean to interpret numbers as reals. - open scoped Real namespace Real -theorem pi_gt_sqrtTwoAddSeries (n : ℕ) : - (2 : ℝ) ^ (n + 1) * √(2 - sqrtTwoAddSeries 0 n) < π := by - have : √(2 - sqrtTwoAddSeries 0 n) / (2 : ℝ) * (2 : ℝ) ^ (n + 2) < π := by +theorem pi_gt_sqrtTwoAddSeries (n : ℕ) : 2 ^ (n + 1) * √(2 - sqrtTwoAddSeries 0 n) < π := by + have : √(2 - sqrtTwoAddSeries 0 n) / 2 * 2 ^ (n + 2) < π := by rw [← lt_div_iff, ← sin_pi_over_two_pow_succ] focus apply sin_lt apply div_pos pi_pos all_goals apply pow_pos; norm_num - apply lt_of_le_of_lt (le_of_eq _) this + refine lt_of_le_of_lt (le_of_eq ?_) this rw [pow_succ' _ (n + 1), ← mul_assoc, div_mul_cancel₀, mul_comm]; norm_num theorem pi_lt_sqrtTwoAddSeries (n : ℕ) : - π < (2 : ℝ) ^ (n + 1) * √(2 - sqrtTwoAddSeries 0 n) + 1 / (4 : ℝ) ^ n := by - have : π < - (√(2 - sqrtTwoAddSeries 0 n) / (2 : ℝ) + (1 : ℝ) / ((2 : ℝ) ^ n) ^ 3 / 4) * - (2 : ℝ) ^ (n + 2) := by + π < 2 ^ (n + 1) * √(2 - sqrtTwoAddSeries 0 n) + 1 / 4 ^ n := by + have : π < (√(2 - sqrtTwoAddSeries 0 n) / 2 + 1 / (2 ^ n) ^ 3 / 4) * (2 : ℝ) ^ (n + 2) := by rw [← div_lt_iff (by norm_num), ← sin_pi_over_two_pow_succ] refine lt_of_lt_of_le (lt_add_of_sub_right_lt (sin_gt_sub_cube ?_ ?_)) ?_ · apply div_pos pi_pos; apply pow_pos; norm_num @@ -57,10 +52,8 @@ theorem pi_lt_sqrtTwoAddSeries (n : ℕ) : · rw [← le_div_iff₀ (by norm_num)] refine le_trans ((div_le_div_right ?_).mpr pi_le_four) ?_ · apply pow_pos; norm_num - · simp only [pow_succ', ← div_div, one_div] - -- Porting note: removed `convert le_rfl` - norm_num - apply lt_of_lt_of_le this (le_of_eq _); rw [add_mul]; congr 1 + · ring_nf; rfl + refine lt_of_lt_of_le this (le_of_eq ?_); rw [add_mul]; congr 1 · ring simp only [show (4 : ℝ) = 2 ^ 2 by norm_num, ← pow_mul, div_div, ← pow_add] rw [one_div, one_div, inv_mul_eq_iff_eq_mul₀, eq_comm, mul_inv_eq_iff_eq_mul₀, ← pow_add] @@ -74,7 +67,7 @@ theorem pi_lower_bound_start (n : ℕ) {a} (h : sqrtTwoAddSeries ((0 : ℕ) / (1 : ℕ)) n ≤ (2 : ℝ) - (a / (2 : ℝ) ^ (n + 1)) ^ 2) : a < π := by refine lt_of_le_of_lt ?_ (pi_gt_sqrtTwoAddSeries n); rw [mul_comm] - refine (div_le_iff₀ (pow_pos (by norm_num) _ : (0 : ℝ) < _)).mp (le_sqrt_of_sq_le ?_) + refine (div_le_iff₀ (pow_pos (by norm_num) _)).mp (le_sqrt_of_sq_le ?_) rwa [le_sub_comm, show (0 : ℝ) = (0 : ℕ) / (1 : ℕ) by rw [Nat.cast_zero, zero_div]] theorem sqrtTwoAddSeries_step_up (c d : ℕ) {a b n : ℕ} {z : ℝ} (hz : sqrtTwoAddSeries (c / d) n ≤ z) @@ -87,35 +80,6 @@ theorem sqrtTwoAddSeries_step_up (c d : ℕ) {a b n : ℕ} {z : ℝ} (hz : sqrtT add_div_eq_mul_add_div _ _ (ne_of_gt hb'), div_le_div_iff hb' (pow_pos hd' _)] exact mod_cast h -section Tactic - -open Lean Elab Tactic - -/-- `numDen stx` takes a syntax expression `stx` and -* if it is of the form `a / b`, then it returns `some (a, b)`; -* otherwise it returns `none`. --/ -private def numDen : Syntax → Option (Syntax.Term × Syntax.Term) - | `($a / $b) => some (a, b) - | _ => none - -/-- Create a proof of `a < π` for a fixed rational number `a`, given a witness, which is a -sequence of rational numbers `√2 < r 1 < r 2 < ... < r n < 2` satisfying the property that -`√(2 + r i) ≤ r(i+1)`, where `r 0 = 0` and `√(2 - r n) ≥ a/2^(n+1)`. -/ -elab "pi_lower_bound " "[" l:term,* "]" : tactic => do - let rat_sep := l.elemsAndSeps - let sep := rat_sep.getD 1 .missing - let ratStx := rat_sep.filter (· != sep) - let n := ← (toExpr ratStx.size).toSyntax - let els := (ratStx.map numDen).reduceOption - evalTactic (← `(tactic| apply pi_lower_bound_start $n)) - let _ := ← els.mapM fun (x, y) => do - evalTactic (← `(tactic| apply sqrtTwoAddSeries_step_up $x $y)) - evalTactic (← `(tactic| simp [sqrtTwoAddSeries])) - allGoals (evalTactic (← `(tactic| norm_num1))) - -end Tactic - /-- From a lower bound on `sqrtTwoAddSeries 0 n = 2 cos (π / 2 ^ (n+1))` of the form `2 - ((a - 1 / 4 ^ n) / 2 ^ (n + 1)) ^ 2 ≤ sqrtTwoAddSeries 0 n`, one can deduce the upper bound `π < a` thanks to basic trigonometric formulas as expressed in `pi_lt_sqrtTwoAddSeries`. -/ @@ -141,52 +105,133 @@ theorem sqrtTwoAddSeries_step_down (a b : ℕ) {c d n : ℕ} {z : ℝ} section Tactic -open Lean Elab Tactic +open Lean Elab Tactic Qq + +/-- Create a proof of `a < π` for a fixed rational number `a`, given a witness, which is a +sequence of rational numbers `√2 < r 1 < r 2 < ... < r n < 2` satisfying the property that +`√(2 + r i) ≤ r(i+1)`, where `r 0 = 0` and `√(2 - r n) ≥ a/2^(n+1)`. -/ +elab "pi_lower_bound " "[" l:term,* "]" : tactic => do + have els := l.getElems + let n := quote els.size + evalTactic (← `(tactic| apply pi_lower_bound_start $n)) + for l in els do + let {num, den, ..} ← unsafe Meta.evalExpr ℚ q(ℚ) (← Term.elabTermAndSynthesize l (some q(ℚ))) + evalTactic (← `(tactic| apply sqrtTwoAddSeries_step_up $(quote num.toNat) $(quote den))) + evalTactic (← `(tactic| simp [sqrtTwoAddSeries])) + allGoals <| evalTactic (← `(tactic| norm_num1)) /-- Create a proof of `π < a` for a fixed rational number `a`, given a witness, which is a sequence of rational numbers `√2 < r 1 < r 2 < ... < r n < 2` satisfying the property that -`√(2 + r i) ≥ r(i+1)`, where `r 0 = 0` and `√(2 - r n) ≥ (a - 1/4^n) / 2^(n+1)`. -/ +`√(2 + r i) ≥ r(i+1)`, where `r 0 = 0` and `√(2 - r n) ≤ (a - 1/4^n) / 2^(n+1)`. -/ elab "pi_upper_bound " "[" l:term,* "]" : tactic => do - let rat_sep := l.elemsAndSeps - let sep := rat_sep.getD 1 .missing - let ratStx := rat_sep.filter (· != sep) - let n := ← (toExpr ratStx.size).toSyntax - let els := (ratStx.map numDen).reduceOption + have els := l.getElems + let n := quote els.size evalTactic (← `(tactic| apply pi_upper_bound_start $n)) - let _ := ← els.mapM fun (x, y) => do - evalTactic (← `(tactic| apply sqrtTwoAddSeries_step_down $x $y)) + for l in els do + let {num, den, ..} ← unsafe Meta.evalExpr ℚ q(ℚ) (← Term.elabTermAndSynthesize l (some q(ℚ))) + evalTactic (← `(tactic| apply sqrtTwoAddSeries_step_down $(quote num.toNat) $(quote den))) evalTactic (← `(tactic| simp [sqrtTwoAddSeries])) - allGoals (evalTactic (← `(tactic| norm_num1))) + allGoals <| evalTactic (← `(tactic| norm_num1)) end Tactic -theorem pi_gt_three : 3 < π := by - pi_lower_bound [23/16] - -theorem pi_gt_314 : 3.14 < π := by - pi_lower_bound [99 / 70, 874 / 473, 1940 / 989, 1447 / 727] - -theorem pi_lt_315 : π < 3.15 := by - pi_upper_bound [140 / 99, 279 / 151, 51 / 26, 412 / 207] - -theorem pi_gt_31415 : 3.1415 < π := by - pi_lower_bound - [11482 / 8119, 5401 / 2923, 2348 / 1197, 11367 / 5711, 25705 / 12868, 23235 / 11621] - -theorem pi_lt_31416 : π < 3.1416 := by - pi_upper_bound - [4756 / 3363, 101211 / 54775, 505534 / 257719, 83289 / 41846, 411278 / 205887, - 438142 / 219137, 451504 / 225769, 265603 / 132804, 849938 / 424971] - -theorem pi_gt_3141592 : 3.141592 < π := by - pi_lower_bound - [11482 / 8119, 7792 / 4217, 54055 / 27557, 949247 / 476920, 3310126 / 1657059, - 2635492 / 1318143, 1580265 / 790192, 1221775 / 610899, 3612247 / 1806132, 849943 / 424972] +/-! +The below witnesses were generated using the following Mathematica script: +```mathematica +bound[a_, Iters -> n_, Rounding -> extra_, Precision -> prec_] := Module[{r0, r, r2, diff, sign}, + On[Assert]; + sign = If[a >= \[Pi], Print["upper"]; 1, Print["lower"]; -1]; + r0 = 2 - ((a - (sign + 1)/2/4^n)/2^(n + 1))^2; + r = Log[2 - NestList[#^2 - 2 &, N[r0, prec], n - 1]]; + diff = (r[[-1]] - Log[2 - Sqrt[2]])/(Length[r] + 1); + If[sign diff <= 0, Return["insufficient iterations"]]; + r2 = Log[Rationalize[Exp[#], extra (Exp[#] - Exp[# - sign diff])] & + /@ (r - diff Range[1, Length[r]])]; + Assert[sign (2 - Exp@r2[[1]] - r0) >= 0]; + Assert[And @@ Table[ + sign (Sqrt@(4 - Exp@r2[[i + 1]]) - (2 - Exp@r2[[i]])) >= 0, {i, 1, Length[r2] - 1}]]; + Assert[sign (Exp@r2[[-1]] - (2 - Sqrt[2])) >= 0]; + With[{s1 = ToString@InputForm[2 - #], s2 = ToString@InputForm[#]}, + If[StringLength[s1] <= StringLength[s2] + 2, s1, "2-" <> s2]] & /@ Exp@Reverse@r2 +]; +``` +-/ -theorem pi_lt_3141593 : π < 3.141593 := by - pi_upper_bound - [27720 / 19601, 56935 / 30813, 49359 / 25163, 258754 / 130003, 113599 / 56868, - 1101994 / 551163, 8671537 / 4336095, 3877807 / 1938940, 52483813 / 26242030, - 56946167 / 28473117, 23798415 / 11899211] +theorem pi_gt_three : 3 < π := by + -- bound[3, Iters -> 1, Rounding -> 2, Precision -> 3] + pi_lower_bound [23 / 16] + +theorem pi_lt_four : π < 4 := by + -- bound[4, Iters -> 1, Rounding -> 1, Precision -> 1] + pi_upper_bound [4 / 3] + +theorem pi_gt_d2 : 3.14 < π := by + -- bound[314*^-2, Iters -> 4, Rounding -> 1.5, Precision -> 8] + pi_lower_bound [338 / 239, 704 / 381, 1940 / 989, 1447 / 727] +@[deprecated (since := "2024-09-19")] alias pi_gt_314 := pi_gt_d2 + +theorem pi_lt_d2 : π < 3.15 := by + -- bound[315*^-2, Iters -> 4, Rounding -> 1.4, Precision -> 7] + pi_upper_bound [41 / 29, 109 / 59, 865 / 441, 412 / 207] +@[deprecated (since := "2024-09-19")] alias pi_lt_315 := pi_lt_d2 + +theorem pi_gt_d4 : 3.1415 < π := by + -- bound[31415*^-4, Iters -> 6, Rounding -> 1.1, Precision -> 10] + pi_lower_bound [ + 1970 / 1393, 3010 / 1629, 11689 / 5959, 10127 / 5088, 33997 / 17019, 23235 / 11621] +@[deprecated (since := "2024-09-19")] alias pi_gt_31415 := pi_gt_d4 + +theorem pi_lt_d4 : π < 3.1416 := by + -- bound[31416*^-4, Iters -> 9, Rounding -> .9, Precision -> 16] + pi_upper_bound [ + 4756/3363, 14965/8099, 21183/10799, 49188/24713, 2-53/22000, 2-71/117869, 2-47/312092, + 2-17/451533, 2-4/424971] +@[deprecated (since := "2024-09-19")] alias pi_lt_31416 := pi_lt_d4 + +theorem pi_gt_d6 : 3.141592 < π := by + -- bound[3141592*^-6, Iters -> 10, Rounding -> .8, Precision -> 16] + pi_lower_bound [ + 11482/8119, 7792/4217, 54055/27557, 2-623/64690, 2-337/139887, 2-208/345307, 2-167/1108925, + 2-64/1699893, 2-31/3293535, 2-48/20398657] +@[deprecated (since := "2024-09-19")] alias pi_gt_3141592 := pi_gt_d6 + +theorem pi_lt_d6 : π < 3.141593 := by + -- bound[3141593*^-6, Iters -> 11, Rounding -> .5, Precision -> 17] + pi_upper_bound [ + 35839/25342, 49143/26596, 145729/74292, 294095/147759, 2-137/56868, 2-471/781921, 2-153/1015961, + 2-157/4170049, 2-28/2974805, 2-9/3824747, 2-7/11899211] +@[deprecated (since := "2024-09-19")] alias pi_lt_3141593 := pi_lt_d6 + +theorem pi_gt_d20 : 3.14159265358979323846 < π := by + -- bound[314159265358979323846*^-20, Iters -> 34, Rounding -> .6, Precision -> 46] + pi_lower_bound [ + 671574048197/474874563549, 58134718954/31462283181, 3090459598621/1575502640777, + 2-7143849599/741790664068, 8431536490061/4220852446654, 2-2725579171/4524814682468, + 2-2494895647/16566776788806, 2-608997841/16175484287402, 2-942567063/100141194694075, + 2-341084060/144951150987041, 2-213717653/363295959742218, 2-71906926/488934711121807, + 2-29337101/797916288104986, 2-45326311/4931175952730065, 2-7506877/3266776448781479, + 2-5854787/10191338039232571, 2-4538642/31601378399861717, 2-276149/7691013341581098, + 2-350197/39013283396653714, 2-442757/197299283738495963, 2-632505/1127415566199968707, + 2-1157/8249230030392285, 2-205461/5859619883403334178, 2-33721/3846807755987625852, + 2-11654/5317837263222296743, 2-8162/14897610345776687857, 2-731/5337002285107943372, + 2-1320/38549072592845336201, 2-707/82588467645883795866, 2-53/24764858756615791675, + 2-237/442963888703240952920, 2-128/956951523274512100791, 2-32/956951523274512100783, + 2-27/3229711391051478340136] + +theorem pi_lt_d20 : π < 3.14159265358979323847 := by + -- bound[314159265358979323847*^-20, Iters -> 34, Rounding -> .5, Precision -> 46] + pi_upper_bound [ + 215157040700/152139002499, 936715022285/506946517009, 1760670193473/897581880893, + 2-6049918861/628200981455, 2-8543385003/3546315642356, 2-2687504973/4461606579043, + 2-1443277808/9583752057175, 2-546886849/14525765179168, 2-650597193/69121426717657, + 2-199969519/84981432264454, 2-226282901/384655467333100, 2-60729699/412934601558121, + 2-25101251/682708800188252, 2-7156464/778571703825145, 2-7524725/3274543383827551, + 2-4663362/8117442793616861, 2-1913009/13319781840326041, 2-115805/3225279830894912, + 2-708749/78957345705688293, 2-131255/58489233342660393, 2-101921/181670219085488669, + 2-44784/319302953916238627, 2-82141/2342610212364552264, 2-4609/525783249231842696, + 2-4567/2083967975041722089, 2-2273/4148770928197796067, 2-563/4110440884426500846, + 2-784/22895812812720260289, 2-1717/200571992854289218531, 2-368/171952226838388893139, + 2-149/278487845640434185590, 2-207/1547570041545500037992, 2-20/598094702046570062987, + 2-7/837332582865198088180] end Real From 124ab81192489ed124caac3129e3f0c62ada63f5 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Fri, 20 Sep 2024 12:33:49 +0000 Subject: [PATCH 066/170] feat(NumberField/CanonicalEmbedding/FundamentalCone): Define the subset of integral points (#16921) Define `fundamentalCone.integralPoint` which is the subset of points in the `fundamentalCone` that are images of algebraic integers. We prove in particular that there is an action of the torsion on `integralPoint` that preserves the norm. This PR is part of the proof of the Analytic Class Number Formula. Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com> --- .../NumberField/CanonicalEmbedding/Basic.lean | 18 ++++ .../CanonicalEmbedding/FundamentalCone.lean | 96 +++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 0d4a68249af32..8e0ff1ca52eca 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -573,6 +573,10 @@ open Module.Free open scoped nonZeroDivisors +/-- The image of the ring of integers of `K` in the mixed space. -/ +protected abbrev integerLattice : Submodule ℤ (mixedSpace K) := + LinearMap.range ((mixedEmbedding K).comp (algebraMap (𝓞 K) K)).toIntAlgHom.toLinearMap + /-- A `ℝ`-basis of the mixed space that is also a `ℤ`-basis of the image of `𝓞 K`. -/ def latticeBasis : Basis (ChooseBasisIndex ℤ (𝓞 K)) ℝ (mixedSpace K) := by @@ -608,6 +612,20 @@ theorem mem_span_latticeBasis (x : (mixedSpace K)) : RingHom.mem_range, exists_exists_eq_and] rfl +theorem span_latticeBasis : + (Submodule.span ℤ (Set.range (latticeBasis K))) = (mixedEmbedding.integerLattice K) := + Submodule.ext_iff.mpr (mem_span_latticeBasis K) + +instance : DiscreteTopology (mixedEmbedding.integerLattice K) := by + classical + rw [← span_latticeBasis] + infer_instance + +open Classical in +instance : IsZLattice ℝ (mixedEmbedding.integerLattice K) := by + simp_rw [← span_latticeBasis] + exact ZSpan.isZLattice (latticeBasis K) + theorem mem_rat_span_latticeBasis (x : K) : mixedEmbedding K x ∈ Submodule.span ℚ (Set.range (latticeBasis K)) := by rw [← Basis.sum_repr (integralBasis K) x, map_sum] diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean index 305679adb9b18..3421bbbf4d554 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean @@ -22,6 +22,9 @@ by multiplication by a nonzero real number, see `smul_mem_of_mem`, that is also domain for the action of `(𝓞 K)ˣ` modulo torsion, see `exists_unit_smul_mem` and `torsion_unit_smul_mem_of_mem`. +* `NumberField.mixedEmbedding.fundamentalCone.integralPoint`: the subset of elements of the +fundamental cone that are images of algebraic integers of `K`. + ## Tags number field, canonical embedding, units, principal ideals @@ -234,6 +237,99 @@ theorem unit_smul_mem_iff_mem_torsion (hx : x ∈ fundamentalCone K) (u : (𝓞 · rw [AddSubmonoid.mk_vadd, vadd_eq_add, zero_add] exact hx.1 +variable (K) in +/-- The set of images by `mixedEmbedding` of algebraic integers of `K` contained in the +fundamental cone. -/ +def integralPoint : Set (mixedSpace K) := + fundamentalCone K ∩ (mixedEmbedding.integerLattice K) + +theorem mem_integralPoint {a : mixedSpace K} : + a ∈ integralPoint K ↔ a ∈ fundamentalCone K ∧ ∃ x : (𝓞 K), mixedEmbedding K x = a:= by + simp only [integralPoint, Set.mem_inter_iff, SetLike.mem_coe, LinearMap.mem_range, + AlgHom.toLinearMap_apply, RingHom.toIntAlgHom_coe, RingHom.coe_comp, Function.comp_apply] + +/-- If `a` is an integral point, then there is a *unique* algebraic integer in `𝓞 K` such +that `mixedEmbedding K x = a`. -/ +theorem exists_unique_preimage_of_integralPoint {a : mixedSpace K} (ha : a ∈ integralPoint K) : + ∃! x : (𝓞 K), mixedEmbedding K x = a := by + obtain ⟨_, ⟨x, rfl⟩⟩ := mem_integralPoint.mp ha + refine Function.Injective.exists_unique_of_mem_range ?_ (Set.mem_range_self x) + exact (mixedEmbedding_injective K).comp RingOfIntegers.coe_injective + +theorem integralPoint_ne_zero (a : integralPoint K) : (a : mixedSpace K) ≠ 0 := by + by_contra! + exact a.prop.1.2 (this.symm ▸ mixedEmbedding.norm.map_zero') + +open scoped nonZeroDivisors + +/-- For `a : integralPoint K`, the unique nonzero algebraic integer whose image by +`mixedEmbedding` is equal to `a`, see `mixedEmbedding_preimageOfIntegralPoint`. -/ +def preimageOfIntegralPoint (a : integralPoint K) : (𝓞 K)⁰ := + ⟨(mem_integralPoint.mp a.prop).2.choose, mem_nonZeroDivisors_of_ne_zero (by + simp_rw [ne_eq, ← RingOfIntegers.coe_injective.eq_iff, ← (mixedEmbedding_injective K).eq_iff, + map_zero, (mem_integralPoint.mp a.prop).2.choose_spec, integralPoint_ne_zero, + not_false_eq_true])⟩ + +@[simp] +theorem mixedEmbedding_preimageOfIntegralPoint (a : integralPoint K) : + mixedEmbedding K (preimageOfIntegralPoint a : 𝓞 K) = (a : mixedSpace K) := by + rw [preimageOfIntegralPoint, (mem_integralPoint.mp a.prop).2.choose_spec] + +theorem preimageOfIntegralPoint_mixedEmbedding {x : (𝓞 K)⁰} + (hx : mixedEmbedding K (x : 𝓞 K) ∈ integralPoint K) : + preimageOfIntegralPoint (⟨mixedEmbedding K (x : 𝓞 K), hx⟩) = x := by + simp_rw [Subtype.ext_iff, RingOfIntegers.ext_iff, ← (mixedEmbedding_injective K).eq_iff, + mixedEmbedding_preimageOfIntegralPoint] + +/-- If `x : mixedSpace K` is nonzero and the image of an algebraic integer, then there exists a +unit such that `u • x ∈ integralPoint K`. -/ +theorem exists_unitSMul_mem_integralPoint {x : mixedSpace K} (hx : x ≠ 0) + (hx' : x ∈ mixedEmbedding K '' (Set.range (algebraMap (𝓞 K) K))) : + ∃ u : (𝓞 K)ˣ, u • x ∈ integralPoint K := by + replace hx : mixedEmbedding.norm x ≠ 0 := + (norm_eq_zero_iff' (Set.mem_range_of_mem_image (mixedEmbedding K) _ hx')).not.mpr hx + obtain ⟨u, hu⟩ := exists_unit_smul_mem hx + obtain ⟨_, ⟨x, rfl⟩, _, rfl⟩ := hx' + exact ⟨u, mem_integralPoint.mpr ⟨hu, u * x, by simp_rw [unitSMul_smul, ← map_mul]⟩⟩ + +/-- The set `integralPoint K` is stable under the action of the torsion. -/ +theorem torsion_unitSMul_mem_integralPoint {x : mixedSpace K} {ζ : (𝓞 K)ˣ} (hζ : ζ ∈ torsion K) + (hx : x ∈ integralPoint K) : ζ • x ∈ integralPoint K := by + obtain ⟨a, ⟨_, rfl⟩, rfl⟩ := (mem_integralPoint.mp hx).2 + refine mem_integralPoint.mpr ⟨torsion_smul_mem_of_mem hx.1 hζ, ⟨ζ * a, by simp⟩⟩ + +/-- The action of `torsion K` on `integralPoint K`. -/ +@[simps] +instance integralPoint_torsionSMul: SMul (torsion K) (integralPoint K) where + smul := fun ⟨ζ, hζ⟩ ⟨x, hx⟩ ↦ ⟨ζ • x, torsion_unitSMul_mem_integralPoint hζ hx⟩ + +instance : MulAction (torsion K) (integralPoint K) where + one_smul := fun _ ↦ by + rw [Subtype.mk_eq_mk, integralPoint_torsionSMul_smul_coe, OneMemClass.coe_one, one_smul] + mul_smul := fun _ _ _ ↦ by + rw [Subtype.mk_eq_mk] + simp_rw [integralPoint_torsionSMul_smul_coe, Subgroup.coe_mul, mul_smul] + +/-- The `mixedEmbedding.norm` of `a : integralPoint K` as a natural number, see also +`intNorm_coe`. -/ +def intNorm (a : integralPoint K) : ℕ := (Algebra.norm ℤ (preimageOfIntegralPoint a : 𝓞 K)).natAbs + +@[simp] +theorem intNorm_coe (a : integralPoint K) : + (intNorm a : ℝ) = mixedEmbedding.norm (a : mixedSpace K) := by + rw [intNorm, Int.cast_natAbs, ← Rat.cast_intCast, Int.cast_abs, Algebra.coe_norm_int, + ← norm_eq_norm, mixedEmbedding_preimageOfIntegralPoint] + +/-- The norm `intNorm` lifts to a function on `integralPoint K` modulo `torsion K`. -/ +def quotIntNorm : + Quotient (MulAction.orbitRel (torsion K) (integralPoint K)) → ℕ := + Quotient.lift (fun x ↦ intNorm x) fun a b ⟨u, hu⟩ ↦ by + rw [← Nat.cast_inj (R := ℝ), intNorm_coe, intNorm_coe, ← hu, integralPoint_torsionSMul_smul_coe, + norm_unit_smul] + +@[simp] +theorem quotIntNorm_apply (a : integralPoint K) : quotIntNorm ⟦a⟧ = intNorm a := rfl + end fundamentalCone end From 87c93626b51f79de48f5fdca516f3a0b2deb9cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Palalansouk=C3=AE?= Date: Fri, 20 Sep 2024 12:45:46 +0000 Subject: [PATCH 067/170] =?UTF-8?q?doc:=20Add=20G=C3=B6del's=20Incompleten?= =?UTF-8?q?ess=20Theorem=20to=20Freek's=20list=20(#16968)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add formalized proofs of Gödel's first and second incompleteness theorem to Freek Wiedijk's list. I may have the wrong notation to describe multiple theorems, please tell me if it is. --- docs/100.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/100.yaml b/docs/100.yaml index d10c937e7c0eb..733af55cb0669 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -18,6 +18,12 @@ title : Prime Number Theorem 6: title : Gödel’s Incompleteness Theorem + author : Shogo Saito + links : + results : + - First: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/First.lean + - Second: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/Second.lean + website: https://formalizedformallogic.github.io/Book/ 7: title : Law of Quadratic Reciprocity decls : From 1912fa595ab1c64d9f3372774c665f6455896bb2 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Fri, 20 Sep 2024 16:59:27 +0000 Subject: [PATCH 068/170] chore: move things around in the `Analytic` folder (#16972) We move some things in the `Analytic` folder, particularly in and out of `Basic`. Notably * The fact that the addition and subtraction are analytic is moved from `Basic` to `Constructions`, where there are already the same facts for multiplication and scalar multiplication * Congruence lemmas are moved from `Within` to `Basic` * Uniqueness of power series is moved from `Basic` to the (already existing file!) `Uniqueness` * Order of imports is swapped between `Calculus.FDeriv.Analytic` and `Analytic.Within`. We also add a few docstrings to the files to show their structure. This gives a more principled hierarchy, better suited to the addition of future lemmas. This PR is just moving things around, no statement has been added or removed. --- Mathlib/Analysis/Analytic/Basic.lean | 415 +++++------------- Mathlib/Analysis/Analytic/CPolynomial.lean | 1 + Mathlib/Analysis/Analytic/ChangeOrigin.lean | 2 +- Mathlib/Analysis/Analytic/Constructions.lean | 151 +++++++ Mathlib/Analysis/Analytic/Uniqueness.lean | 133 +++++- Mathlib/Analysis/Analytic/Within.lean | 83 +--- .../Analysis/Calculus/FDeriv/Analytic.lean | 15 +- Mathlib/Analysis/Complex/CauchyIntegral.lean | 1 + .../Geometry/Manifold/AnalyticManifold.lean | 2 +- 9 files changed, 407 insertions(+), 396 deletions(-) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index a8d94d40086a9..995fbba71ec66 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -63,10 +63,6 @@ We develop the basic properties of these notions, notably: `AnalyticAt.continuousAt`). * In a complete space, the sum of a formal power series with positive radius is well defined on the disk of convergence, see `FormalMultilinearSeries.hasFPowerSeriesOnBall`. -* If a function admits a power series in a ball, then it is analytic at any point `y` of this ball, - and the power series there can be expressed in terms of the initial power series `p` as - `p.changeOrigin y`. See `HasFPowerSeriesOnBall.changeOrigin`. It follows in particular that - the set of points at which a given function is analytic is open, see `isOpen_analyticAt`. ## Implementation details @@ -396,6 +392,10 @@ this is weaker than `AnalyticOn 𝕜 f s`, as `f` is allowed to be arbitrary out def AnalyticWithinOn (f : E → F) (s : Set E) : Prop := ∀ x ∈ s, AnalyticWithinAt 𝕜 f s x +/-! +### `HasFPowerSeriesOnBall` and `HasFPowerSeriesWithinOnBall` +-/ + variable {𝕜} theorem HasFPowerSeriesOnBall.hasFPowerSeriesAt (hf : HasFPowerSeriesOnBall f p x r) : @@ -419,15 +419,6 @@ theorem HasFPowerSeriesWithinOnBall.analyticWithinAt (hf : HasFPowerSeriesWithin AnalyticWithinAt 𝕜 f s x := hf.hasFPowerSeriesWithinAt.analyticWithinAt -theorem HasFPowerSeriesOnBall.congr (hf : HasFPowerSeriesOnBall f p x r) - (hg : EqOn f g (EMetric.ball x r)) : HasFPowerSeriesOnBall g p x r := - { r_le := hf.r_le - r_pos := hf.r_pos - hasSum := fun {y} hy => by - convert hf.hasSum hy using 1 - apply hg.symm - simpa [edist_eq_coe_nnnorm_sub] using hy } - /-- If a function `f` has a power series `p` around `x`, then the function `z ↦ f (z - y)` has the same power series around `x + y`. -/ theorem HasFPowerSeriesOnBall.comp_sub (hf : HasFPowerSeriesOnBall f p x r) (y : E) : @@ -470,6 +461,42 @@ theorem HasFPowerSeriesOnBall.mono (hf : HasFPowerSeriesOnBall f p x r) (r'_pos (hr : r' ≤ r) : HasFPowerSeriesOnBall f p x r' := ⟨le_trans hr hf.1, r'_pos, fun hy => hf.hasSum (EMetric.ball_subset_ball hr hy)⟩ +lemma HasFPowerSeriesWithinOnBall.congr {f g : E → F} {p : FormalMultilinearSeries 𝕜 E F} + {s : Set E} {x : E} {r : ℝ≥0∞} (h : HasFPowerSeriesWithinOnBall f p s x r) + (h' : EqOn g f (s ∩ EMetric.ball x r)) (h'' : g x = f x) : + HasFPowerSeriesWithinOnBall g p s x r := by + refine ⟨h.r_le, h.r_pos, ?_⟩ + intro y hy h'y + convert h.hasSum hy h'y using 1 + simp only [mem_insert_iff, add_right_eq_self] at hy + rcases hy with rfl | hy + · simpa using h'' + · apply h' + refine ⟨hy, ?_⟩ + simpa [edist_eq_coe_nnnorm_sub] using h'y + +lemma HasFPowerSeriesWithinAt.congr {f g : E → F} {p : FormalMultilinearSeries 𝕜 E F} {s : Set E} + {x : E} (h : HasFPowerSeriesWithinAt f p s x) (h' : g =ᶠ[𝓝[s] x] f) (h'' : g x = f x) : + HasFPowerSeriesWithinAt g p s x := by + rcases h with ⟨r, hr⟩ + obtain ⟨ε, εpos, hε⟩ : ∃ ε > 0, EMetric.ball x ε ∩ s ⊆ {y | g y = f y} := + EMetric.mem_nhdsWithin_iff.1 h' + let r' := min r ε + refine ⟨r', ?_⟩ + have := hr.of_le (r' := r') (by simp [r', εpos, hr.r_pos]) (min_le_left _ _) + apply this.congr _ h'' + intro z hz + exact hε ⟨EMetric.ball_subset_ball (min_le_right _ _) hz.2, hz.1⟩ + +theorem HasFPowerSeriesOnBall.congr (hf : HasFPowerSeriesOnBall f p x r) + (hg : EqOn f g (EMetric.ball x r)) : HasFPowerSeriesOnBall g p x r := + { r_le := hf.r_le + r_pos := hf.r_pos + hasSum := fun {y} hy => by + convert hf.hasSum hy using 1 + apply hg.symm + simpa [edist_eq_coe_nnnorm_sub] using hy } + theorem HasFPowerSeriesAt.congr (hf : HasFPowerSeriesAt f p x) (hg : f =ᶠ[𝓝 x] g) : HasFPowerSeriesAt g p x := by rcases hf with ⟨r₁, h₁⟩ @@ -530,14 +557,6 @@ theorem HasFPowerSeriesAt.eventually_eq_zero HasFPowerSeriesWithinAt f p univ x ↔ HasFPowerSeriesAt f p x := by simp only [HasFPowerSeriesWithinAt, hasFPowerSeriesWithinOnBall_univ, HasFPowerSeriesAt] -@[simp] lemma analyticWithinAt_univ : - AnalyticWithinAt 𝕜 f univ x ↔ AnalyticAt 𝕜 f x := by - simp [AnalyticWithinAt, AnalyticAt] - -@[simp] lemma analyticWithinOn_univ {f : E → F} : - AnalyticWithinOn 𝕜 f univ ↔ AnalyticOn 𝕜 f univ := by - simp only [AnalyticWithinOn, analyticWithinAt_univ, AnalyticOn] - lemma HasFPowerSeriesWithinOnBall.mono (hf : HasFPowerSeriesWithinOnBall f p s x r) (h : t ⊆ s) : HasFPowerSeriesWithinOnBall f p t x r where r_le := hf.r_le @@ -559,6 +578,44 @@ lemma HasFPowerSeriesAt.hasFPowerSeriesWithinAt (hf : HasFPowerSeriesAt f p x) : rw [← hasFPowerSeriesWithinAt_univ] at hf apply hf.mono (subset_univ _) +theorem HasFPowerSeriesWithinOnBall.coeff_zero (hf : HasFPowerSeriesWithinOnBall f pf s x r) + (v : Fin 0 → E) : pf 0 v = f x := by + have v_eq : v = fun i => 0 := Subsingleton.elim _ _ + have zero_mem : (0 : E) ∈ EMetric.ball (0 : E) r := by simp [hf.r_pos] + have : ∀ i, i ≠ 0 → (pf i fun j => 0) = 0 := by + intro i hi + have : 0 < i := pos_iff_ne_zero.2 hi + exact ContinuousMultilinearMap.map_coord_zero _ (⟨0, this⟩ : Fin i) rfl + have A := (hf.hasSum (by simp) zero_mem).unique (hasSum_single _ this) + simpa [v_eq] using A.symm + +theorem HasFPowerSeriesOnBall.coeff_zero (hf : HasFPowerSeriesOnBall f pf x r) + (v : Fin 0 → E) : pf 0 v = f x := by + rw [← hasFPowerSeriesWithinOnBall_univ] at hf + exact hf.coeff_zero v + +theorem HasFPowerSeriesWithinAt.coeff_zero (hf : HasFPowerSeriesWithinAt f pf s x) (v : Fin 0 → E) : + pf 0 v = f x := + let ⟨_, hrf⟩ := hf + hrf.coeff_zero v + +theorem HasFPowerSeriesAt.coeff_zero (hf : HasFPowerSeriesAt f pf x) (v : Fin 0 → E) : + pf 0 v = f x := + let ⟨_, hrf⟩ := hf + hrf.coeff_zero v + +/-! +### Analytic functions +-/ + +@[simp] lemma analyticWithinAt_univ : + AnalyticWithinAt 𝕜 f univ x ↔ AnalyticAt 𝕜 f x := by + simp [AnalyticWithinAt, AnalyticAt] + +@[simp] lemma analyticWithinOn_univ {f : E → F} : + AnalyticWithinOn 𝕜 f univ ↔ AnalyticOn 𝕜 f univ := by + simp only [AnalyticWithinOn, analyticWithinAt_univ, AnalyticOn] + lemma AnalyticWithinAt.mono (hf : AnalyticWithinAt 𝕜 f s x) (h : t ⊆ s) : AnalyticWithinAt 𝕜 f t x := by obtain ⟨p, hp⟩ := hf @@ -571,50 +628,21 @@ lemma AnalyticAt.analyticWithinAt (hf : AnalyticAt 𝕜 f x) : AnalyticWithinAt lemma AnalyticOn.analyticWithinOn (hf : AnalyticOn 𝕜 f s) : AnalyticWithinOn 𝕜 f s := fun x hx ↦ (hf x hx).analyticWithinAt -theorem hasFPowerSeriesOnBall_const {c : F} {e : E} : - HasFPowerSeriesOnBall (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e ⊤ := by - refine ⟨by simp, WithTop.zero_lt_top, fun _ => hasSum_single 0 fun n hn => ?_⟩ - simp [constFormalMultilinearSeries_apply hn] - -theorem hasFPowerSeriesAt_const {c : F} {e : E} : - HasFPowerSeriesAt (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e := - ⟨⊤, hasFPowerSeriesOnBall_const⟩ - -theorem analyticAt_const {v : F} : AnalyticAt 𝕜 (fun _ => v) x := - ⟨constFormalMultilinearSeries 𝕜 E v, hasFPowerSeriesAt_const⟩ - -theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := - fun _ _ => analyticAt_const +lemma AnalyticWithinAt.congr_of_eventuallyEq {f g : E → F} {s : Set E} {x : E} + (hf : AnalyticWithinAt 𝕜 f s x) (hs : g =ᶠ[𝓝[s] x] f) (hx : g x = f x) : + AnalyticWithinAt 𝕜 g s x := by + rcases hf with ⟨p, hp⟩ + exact ⟨p, hp.congr hs hx⟩ -theorem analyticWithinAt_const {v : F} {s : Set E} : AnalyticWithinAt 𝕜 (fun _ => v) s x := - analyticAt_const.analyticWithinAt +lemma AnalyticWithinAt.congr {f g : E → F} {s : Set E} {x : E} + (hf : AnalyticWithinAt 𝕜 f s x) (hs : EqOn g f s) (hx : g x = f x) : + AnalyticWithinAt 𝕜 g s x := + hf.congr_of_eventuallyEq hs.eventuallyEq_nhdsWithin hx -theorem analyticWithinOn_const {v : F} {s : Set E} : AnalyticWithinOn 𝕜 (fun _ => v) s := - analyticOn_const.analyticWithinOn - -theorem HasFPowerSeriesWithinOnBall.add (hf : HasFPowerSeriesWithinOnBall f pf s x r) - (hg : HasFPowerSeriesWithinOnBall g pg s x r) : - HasFPowerSeriesWithinOnBall (f + g) (pf + pg) s x r := - { r_le := le_trans (le_min_iff.2 ⟨hf.r_le, hg.r_le⟩) (pf.min_radius_le_radius_add pg) - r_pos := hf.r_pos - hasSum := fun hy h'y => (hf.hasSum hy h'y).add (hg.hasSum hy h'y) } - -theorem HasFPowerSeriesOnBall.add (hf : HasFPowerSeriesOnBall f pf x r) - (hg : HasFPowerSeriesOnBall g pg x r) : HasFPowerSeriesOnBall (f + g) (pf + pg) x r := - { r_le := le_trans (le_min_iff.2 ⟨hf.r_le, hg.r_le⟩) (pf.min_radius_le_radius_add pg) - r_pos := hf.r_pos - hasSum := fun hy => (hf.hasSum hy).add (hg.hasSum hy) } - -theorem HasFPowerSeriesWithinAt.add - (hf : HasFPowerSeriesWithinAt f pf s x) (hg : HasFPowerSeriesWithinAt g pg s x) : - HasFPowerSeriesWithinAt (f + g) (pf + pg) s x := by - rcases (hf.eventually.and hg.eventually).exists with ⟨r, hr⟩ - exact ⟨r, hr.1.add hr.2⟩ - -theorem HasFPowerSeriesAt.add (hf : HasFPowerSeriesAt f pf x) (hg : HasFPowerSeriesAt g pg x) : - HasFPowerSeriesAt (f + g) (pf + pg) x := by - rcases (hf.eventually.and hg.eventually).exists with ⟨r, hr⟩ - exact ⟨r, hr.1.add hr.2⟩ +lemma AnalyticWithinOn.congr {f g : E → F} {s : Set E} + (hf : AnalyticWithinOn 𝕜 f s) (hs : EqOn g f s) : + AnalyticWithinOn 𝕜 g s := + fun x m ↦ (hf x m).congr hs (hs m) theorem AnalyticAt.congr (hf : AnalyticAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : AnalyticAt 𝕜 g x := let ⟨_, hpf⟩ := hf @@ -623,76 +651,6 @@ theorem AnalyticAt.congr (hf : AnalyticAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : An theorem analyticAt_congr (h : f =ᶠ[𝓝 x] g) : AnalyticAt 𝕜 f x ↔ AnalyticAt 𝕜 g x := ⟨fun hf ↦ hf.congr h, fun hg ↦ hg.congr h.symm⟩ -theorem AnalyticWithinAt.add (hf : AnalyticWithinAt 𝕜 f s x) (hg : AnalyticWithinAt 𝕜 g s x) : - AnalyticWithinAt 𝕜 (f + g) s x := - let ⟨_, hpf⟩ := hf - let ⟨_, hqf⟩ := hg - (hpf.add hqf).analyticWithinAt - -theorem AnalyticAt.add (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : AnalyticAt 𝕜 (f + g) x := - let ⟨_, hpf⟩ := hf - let ⟨_, hqf⟩ := hg - (hpf.add hqf).analyticAt - -theorem HasFPowerSeriesWithinOnBall.neg (hf : HasFPowerSeriesWithinOnBall f pf s x r) : - HasFPowerSeriesWithinOnBall (-f) (-pf) s x r := - { r_le := by - rw [pf.radius_neg] - exact hf.r_le - r_pos := hf.r_pos - hasSum := fun hy h'y => (hf.hasSum hy h'y).neg } - -theorem HasFPowerSeriesOnBall.neg (hf : HasFPowerSeriesOnBall f pf x r) : - HasFPowerSeriesOnBall (-f) (-pf) x r := - { r_le := by - rw [pf.radius_neg] - exact hf.r_le - r_pos := hf.r_pos - hasSum := fun hy => (hf.hasSum hy).neg } - -theorem HasFPowerSeriesWithinAt.neg (hf : HasFPowerSeriesWithinAt f pf s x) : - HasFPowerSeriesWithinAt (-f) (-pf) s x := - let ⟨_, hrf⟩ := hf - hrf.neg.hasFPowerSeriesWithinAt - -theorem HasFPowerSeriesAt.neg (hf : HasFPowerSeriesAt f pf x) : HasFPowerSeriesAt (-f) (-pf) x := - let ⟨_, hrf⟩ := hf - hrf.neg.hasFPowerSeriesAt - -theorem AnalyticWithinAt.neg (hf : AnalyticWithinAt 𝕜 f s x) : AnalyticWithinAt 𝕜 (-f) s x := - let ⟨_, hpf⟩ := hf - hpf.neg.analyticWithinAt - -theorem AnalyticAt.neg (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (-f) x := - let ⟨_, hpf⟩ := hf - hpf.neg.analyticAt - -theorem HasFPowerSeriesWithinOnBall.sub (hf : HasFPowerSeriesWithinOnBall f pf s x r) - (hg : HasFPowerSeriesWithinOnBall g pg s x r) : - HasFPowerSeriesWithinOnBall (f - g) (pf - pg) s x r := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - -theorem HasFPowerSeriesOnBall.sub (hf : HasFPowerSeriesOnBall f pf x r) - (hg : HasFPowerSeriesOnBall g pg x r) : HasFPowerSeriesOnBall (f - g) (pf - pg) x r := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - -theorem HasFPowerSeriesWithinAt.sub - (hf : HasFPowerSeriesWithinAt f pf s x) (hg : HasFPowerSeriesWithinAt g pg s x) : - HasFPowerSeriesWithinAt (f - g) (pf - pg) s x := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - -theorem HasFPowerSeriesAt.sub (hf : HasFPowerSeriesAt f pf x) (hg : HasFPowerSeriesAt g pg x) : - HasFPowerSeriesAt (f - g) (pf - pg) x := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - -theorem AnalyticWithinAt.sub (hf : AnalyticWithinAt 𝕜 f s x) (hg : AnalyticWithinAt 𝕜 g s x) : - AnalyticWithinAt 𝕜 (f - g) s x := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - -theorem AnalyticAt.sub (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : - AnalyticAt 𝕜 (f - g) x := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - theorem AnalyticOn.mono {s t : Set E} (hf : AnalyticOn 𝕜 f t) (hst : s ⊆ t) : AnalyticOn 𝕜 f s := fun z hz => hf z (hst hz) @@ -711,53 +669,13 @@ theorem AnalyticOn.congr (hs : IsOpen s) (hf : AnalyticOn 𝕜 f s) (hg : s.EqOn theorem analyticOn_congr (hs : IsOpen s) (h : s.EqOn f g) : AnalyticOn 𝕜 f s ↔ AnalyticOn 𝕜 g s := ⟨fun hf => hf.congr hs h, fun hg => hg.congr hs h.symm⟩ -theorem AnalyticWithinOn.add (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (f + g) s := - fun z hz => (hf z hz).add (hg z hz) - -theorem AnalyticOn.add (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : - AnalyticOn 𝕜 (f + g) s := - fun z hz => (hf z hz).add (hg z hz) - -theorem AnalyticWithinOn.neg (hf : AnalyticWithinOn 𝕜 f s) : AnalyticWithinOn 𝕜 (-f) s := - fun z hz ↦ (hf z hz).neg - -theorem AnalyticOn.neg (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (-f) s := - fun z hz ↦ (hf z hz).neg - -theorem AnalyticWithinOn.sub (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (f - g) s := - fun z hz => (hf z hz).sub (hg z hz) - -theorem AnalyticOn.sub (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : - AnalyticOn 𝕜 (f - g) s := - fun z hz => (hf z hz).sub (hg z hz) - -theorem HasFPowerSeriesWithinOnBall.coeff_zero (hf : HasFPowerSeriesWithinOnBall f pf s x r) - (v : Fin 0 → E) : pf 0 v = f x := by - have v_eq : v = fun i => 0 := Subsingleton.elim _ _ - have zero_mem : (0 : E) ∈ EMetric.ball (0 : E) r := by simp [hf.r_pos] - have : ∀ i, i ≠ 0 → (pf i fun j => 0) = 0 := by - intro i hi - have : 0 < i := pos_iff_ne_zero.2 hi - exact ContinuousMultilinearMap.map_coord_zero _ (⟨0, this⟩ : Fin i) rfl - have A := (hf.hasSum (by simp) zero_mem).unique (hasSum_single _ this) - simpa [v_eq] using A.symm - -theorem HasFPowerSeriesOnBall.coeff_zero (hf : HasFPowerSeriesOnBall f pf x r) - (v : Fin 0 → E) : pf 0 v = f x := by - rw [← hasFPowerSeriesWithinOnBall_univ] at hf - exact hf.coeff_zero v - -theorem HasFPowerSeriesWithinAt.coeff_zero (hf : HasFPowerSeriesWithinAt f pf s x) (v : Fin 0 → E) : - pf 0 v = f x := - let ⟨_, hrf⟩ := hf - hrf.coeff_zero v +lemma AnalyticWithinOn.mono {f : E → F} {s t : Set E} (h : AnalyticWithinOn 𝕜 f t) + (hs : s ⊆ t) : AnalyticWithinOn 𝕜 f s := + fun _ m ↦ (h _ (hs m)).mono hs -theorem HasFPowerSeriesAt.coeff_zero (hf : HasFPowerSeriesAt f pf x) (v : Fin 0 → E) : - pf 0 v = f x := - let ⟨_, hrf⟩ := hf - hrf.coeff_zero v +/-! +### Composition with linear maps +-/ /-- If a function `f` has a power series `p` on a ball and `g` is linear, then `g ∘ f` has the power series `g ∘ p` on the same ball. -/ @@ -779,6 +697,10 @@ theorem ContinuousLinearMap.comp_analyticOn {s : Set E} (g : F →L[𝕜] G) (h rcases h x hx with ⟨p, r, hp⟩ exact ⟨g.compFormalMultilinearSeries p, r, g.comp_hasFPowerSeriesOnBall hp⟩ +/-! +### Relation between analytic function and the partial sums of its power series +-/ + theorem HasFPowerSeriesWithinOnBall.tendsto_partialSum (hf : HasFPowerSeriesWithinOnBall f p s x r) {y : E} (hy : y ∈ EMetric.ball (0 : E) r) (h'y : x + y ∈ insert x s) : @@ -1245,6 +1167,10 @@ protected theorem AnalyticAt.continuousAt (hf : AnalyticAt 𝕜 f x) : Continuou protected theorem AnalyticOn.continuousOn {s : Set E} (hf : AnalyticOn 𝕜 f s) : ContinuousOn f s := fun x hx => (hf x hx).continuousAt.continuousWithinAt +protected lemma AnalyticWithinOn.continuousOn {f : E → F} {s : Set E} (h : AnalyticWithinOn 𝕜 f s) : + ContinuousOn f s := + fun x m ↦ (h x m).continuousWithinAt + /-- Analytic everywhere implies continuous -/ theorem AnalyticOn.continuous {f : E → F} (fa : AnalyticOn 𝕜 f univ) : Continuous f := by rw [continuous_iff_continuousOn_univ]; exact fa.continuousOn @@ -1273,137 +1199,6 @@ protected theorem FormalMultilinearSeries.continuousOn [CompleteSpace F] : end -/-! -### Uniqueness of power series -If a function `f : E → F` has two representations as power series at a point `x : E`, corresponding -to formal multilinear series `p₁` and `p₂`, then these representations agree term-by-term. That is, -for any `n : ℕ` and `y : E`, `p₁ n (fun i ↦ y) = p₂ n (fun i ↦ y)`. In the one-dimensional case, -when `f : 𝕜 → E`, the continuous multilinear maps `p₁ n` and `p₂ n` are given by -`ContinuousMultilinearMap.mkPiRing`, and hence are determined completely by the value of -`p₁ n (fun i ↦ 1)`, so `p₁ = p₂`. Consequently, the radius of convergence for one series can be -transferred to the other. --/ - - -section Uniqueness - -open ContinuousMultilinearMap - -theorem Asymptotics.IsBigO.continuousMultilinearMap_apply_eq_zero {n : ℕ} {p : E[×n]→L[𝕜] F} - (h : (fun y => p fun _ => y) =O[𝓝 0] fun y => ‖y‖ ^ (n + 1)) (y : E) : (p fun _ => y) = 0 := by - obtain ⟨c, c_pos, hc⟩ := h.exists_pos - obtain ⟨t, ht, t_open, z_mem⟩ := eventually_nhds_iff.mp (isBigOWith_iff.mp hc) - obtain ⟨δ, δ_pos, δε⟩ := (Metric.isOpen_iff.mp t_open) 0 z_mem - clear h hc z_mem - cases' n with n - · exact norm_eq_zero.mp (by - -- Porting note: the symmetric difference of the `simpa only` sets: - -- added `zero_add, pow_one` - -- removed `zero_pow, Ne.def, Nat.one_ne_zero, not_false_iff` - simpa only [fin0_apply_norm, norm_eq_zero, norm_zero, zero_add, pow_one, - mul_zero, norm_le_zero_iff] using ht 0 (δε (Metric.mem_ball_self δ_pos))) - · refine Or.elim (Classical.em (y = 0)) - (fun hy => by simpa only [hy] using p.map_zero) fun hy => ?_ - replace hy := norm_pos_iff.mpr hy - refine norm_eq_zero.mp (le_antisymm (le_of_forall_pos_le_add fun ε ε_pos => ?_) (norm_nonneg _)) - have h₀ := _root_.mul_pos c_pos (pow_pos hy (n.succ + 1)) - obtain ⟨k, k_pos, k_norm⟩ := NormedField.exists_norm_lt 𝕜 - (lt_min (mul_pos δ_pos (inv_pos.mpr hy)) (mul_pos ε_pos (inv_pos.mpr h₀))) - have h₁ : ‖k • y‖ < δ := by - rw [norm_smul] - exact inv_mul_cancel_right₀ hy.ne.symm δ ▸ - mul_lt_mul_of_pos_right (lt_of_lt_of_le k_norm (min_le_left _ _)) hy - have h₂ := - calc - ‖p fun _ => k • y‖ ≤ c * ‖k • y‖ ^ (n.succ + 1) := by - -- Porting note: now Lean wants `_root_.` - simpa only [norm_pow, _root_.norm_norm] using ht (k • y) (δε (mem_ball_zero_iff.mpr h₁)) - --simpa only [norm_pow, norm_norm] using ht (k • y) (δε (mem_ball_zero_iff.mpr h₁)) - _ = ‖k‖ ^ n.succ * (‖k‖ * (c * ‖y‖ ^ (n.succ + 1))) := by - -- Porting note: added `Nat.succ_eq_add_one` since otherwise `ring` does not conclude. - simp only [norm_smul, mul_pow, Nat.succ_eq_add_one] - -- Porting note: removed `rw [pow_succ]`, since it now becomes superfluous. - ring - have h₃ : ‖k‖ * (c * ‖y‖ ^ (n.succ + 1)) < ε := - inv_mul_cancel_right₀ h₀.ne.symm ε ▸ - mul_lt_mul_of_pos_right (lt_of_lt_of_le k_norm (min_le_right _ _)) h₀ - calc - ‖p fun _ => y‖ = ‖k⁻¹ ^ n.succ‖ * ‖p fun _ => k • y‖ := by - simpa only [inv_smul_smul₀ (norm_pos_iff.mp k_pos), norm_smul, Finset.prod_const, - Finset.card_fin] using - congr_arg norm (p.map_smul_univ (fun _ : Fin n.succ => k⁻¹) fun _ : Fin n.succ => k • y) - _ ≤ ‖k⁻¹ ^ n.succ‖ * (‖k‖ ^ n.succ * (‖k‖ * (c * ‖y‖ ^ (n.succ + 1)))) := by gcongr - _ = ‖(k⁻¹ * k) ^ n.succ‖ * (‖k‖ * (c * ‖y‖ ^ (n.succ + 1))) := by - rw [← mul_assoc] - simp [norm_mul, mul_pow] - _ ≤ 0 + ε := by - rw [inv_mul_cancel₀ (norm_pos_iff.mp k_pos)] - simpa using h₃.le - -/-- If a formal multilinear series `p` represents the zero function at `x : E`, then the -terms `p n (fun i ↦ y)` appearing in the sum are zero for any `n : ℕ`, `y : E`. -/ -theorem HasFPowerSeriesAt.apply_eq_zero {p : FormalMultilinearSeries 𝕜 E F} {x : E} - (h : HasFPowerSeriesAt 0 p x) (n : ℕ) : ∀ y : E, (p n fun _ => y) = 0 := by - refine Nat.strong_induction_on n fun k hk => ?_ - have psum_eq : p.partialSum (k + 1) = fun y => p k fun _ => y := by - funext z - refine Finset.sum_eq_single _ (fun b hb hnb => ?_) fun hn => ?_ - · have := Finset.mem_range_succ_iff.mp hb - simp only [hk b (this.lt_of_ne hnb), Pi.zero_apply] - · exact False.elim (hn (Finset.mem_range.mpr (lt_add_one k))) - replace h := h.isBigO_sub_partialSum_pow k.succ - simp only [psum_eq, zero_sub, Pi.zero_apply, Asymptotics.isBigO_neg_left] at h - exact h.continuousMultilinearMap_apply_eq_zero - -/-- A one-dimensional formal multilinear series representing the zero function is zero. -/ -theorem HasFPowerSeriesAt.eq_zero {p : FormalMultilinearSeries 𝕜 𝕜 E} {x : 𝕜} - (h : HasFPowerSeriesAt 0 p x) : p = 0 := by - ext n x - rw [← mkPiRing_apply_one_eq_self (p n)] - simp [h.apply_eq_zero n 1] - -/-- One-dimensional formal multilinear series representing the same function are equal. -/ -theorem HasFPowerSeriesAt.eq_formalMultilinearSeries {p₁ p₂ : FormalMultilinearSeries 𝕜 𝕜 E} - {f : 𝕜 → E} {x : 𝕜} (h₁ : HasFPowerSeriesAt f p₁ x) (h₂ : HasFPowerSeriesAt f p₂ x) : p₁ = p₂ := - sub_eq_zero.mp (HasFPowerSeriesAt.eq_zero (x := x) (by simpa only [sub_self] using h₁.sub h₂)) - -theorem HasFPowerSeriesAt.eq_formalMultilinearSeries_of_eventually - {p q : FormalMultilinearSeries 𝕜 𝕜 E} {f g : 𝕜 → E} {x : 𝕜} (hp : HasFPowerSeriesAt f p x) - (hq : HasFPowerSeriesAt g q x) (heq : ∀ᶠ z in 𝓝 x, f z = g z) : p = q := - (hp.congr heq).eq_formalMultilinearSeries hq - -/-- A one-dimensional formal multilinear series representing a locally zero function is zero. -/ -theorem HasFPowerSeriesAt.eq_zero_of_eventually {p : FormalMultilinearSeries 𝕜 𝕜 E} {f : 𝕜 → E} - {x : 𝕜} (hp : HasFPowerSeriesAt f p x) (hf : f =ᶠ[𝓝 x] 0) : p = 0 := - (hp.congr hf).eq_zero - -/-- If a function `f : 𝕜 → E` has two power series representations at `x`, then the given radii in -which convergence is guaranteed may be interchanged. This can be useful when the formal multilinear -series in one representation has a particularly nice form, but the other has a larger radius. -/ -theorem HasFPowerSeriesOnBall.exchange_radius {p₁ p₂ : FormalMultilinearSeries 𝕜 𝕜 E} {f : 𝕜 → E} - {r₁ r₂ : ℝ≥0∞} {x : 𝕜} (h₁ : HasFPowerSeriesOnBall f p₁ x r₁) - (h₂ : HasFPowerSeriesOnBall f p₂ x r₂) : HasFPowerSeriesOnBall f p₁ x r₂ := - h₂.hasFPowerSeriesAt.eq_formalMultilinearSeries h₁.hasFPowerSeriesAt ▸ h₂ - -/-- If a function `f : 𝕜 → E` has power series representation `p` on a ball of some radius and for -each positive radius it has some power series representation, then `p` converges to `f` on the whole -`𝕜`. -/ -theorem HasFPowerSeriesOnBall.r_eq_top_of_exists {f : 𝕜 → E} {r : ℝ≥0∞} {x : 𝕜} - {p : FormalMultilinearSeries 𝕜 𝕜 E} (h : HasFPowerSeriesOnBall f p x r) - (h' : ∀ (r' : ℝ≥0) (_ : 0 < r'), ∃ p' : FormalMultilinearSeries 𝕜 𝕜 E, - HasFPowerSeriesOnBall f p' x r') : - HasFPowerSeriesOnBall f p x ∞ := - { r_le := ENNReal.le_of_forall_pos_nnreal_lt fun r hr _ => - let ⟨_, hp'⟩ := h' r hr - (h.exchange_radius hp').r_le - r_pos := ENNReal.coe_lt_top - hasSum := fun {y} _ => - let ⟨r', hr'⟩ := exists_gt ‖y‖₊ - let ⟨_, hp'⟩ := h' r' hr'.ne_bot.bot_lt - (h.exchange_radius hp').hasSum <| mem_emetric_ball_zero_iff.mpr (ENNReal.coe_lt_coe.2 hr') } - -end Uniqueness - section open FormalMultilinearSeries diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean index c9271baf1873a..bda50d02ecbfb 100644 --- a/Mathlib/Analysis/Analytic/CPolynomial.lean +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sophie Morel -/ import Mathlib.Analysis.Analytic.ChangeOrigin +import Mathlib.Analysis.Analytic.Constructions /-! We specialize the theory fo analytic functions to the case of functions that admit a development given by a *finite* formal multilinear series. We call them "continuously polynomial", diff --git a/Mathlib/Analysis/Analytic/ChangeOrigin.lean b/Mathlib/Analysis/Analytic/ChangeOrigin.lean index 9e2a610834e3a..de0ca613e74d3 100644 --- a/Mathlib/Analysis/Analytic/ChangeOrigin.lean +++ b/Mathlib/Analysis/Analytic/ChangeOrigin.lean @@ -36,7 +36,7 @@ that the set of points at which a given function is analytic is open, see `isOpe noncomputable section open scoped NNReal ENNReal Topology -open Filter +open Filter Set variable {𝕜 E F : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedAddCommGroup F] [NormedSpace 𝕜 F] diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index 4fafa39ac6c71..fb1f04b56cf27 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -31,6 +31,157 @@ variable {E F G H : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedAd variable {𝕝 : Type*} [NontriviallyNormedField 𝕝] [NormedAlgebra 𝕜 𝕝] variable {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] +/-! +### Constants are analytic +-/ + +theorem hasFPowerSeriesOnBall_const {c : F} {e : E} : + HasFPowerSeriesOnBall (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e ⊤ := by + refine ⟨by simp, WithTop.zero_lt_top, fun _ => hasSum_single 0 fun n hn => ?_⟩ + simp [constFormalMultilinearSeries_apply hn] + +theorem hasFPowerSeriesAt_const {c : F} {e : E} : + HasFPowerSeriesAt (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e := + ⟨⊤, hasFPowerSeriesOnBall_const⟩ + +theorem analyticAt_const {v : F} {x : E} : AnalyticAt 𝕜 (fun _ => v) x := + ⟨constFormalMultilinearSeries 𝕜 E v, hasFPowerSeriesAt_const⟩ + +theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := + fun _ _ => analyticAt_const + +theorem analyticWithinAt_const {v : F} {s : Set E} {x : E} : AnalyticWithinAt 𝕜 (fun _ => v) s x := + analyticAt_const.analyticWithinAt + +theorem analyticWithinOn_const {v : F} {s : Set E} : AnalyticWithinOn 𝕜 (fun _ => v) s := + analyticOn_const.analyticWithinOn + +/-! +### Addition, negation, subtraction +-/ + +section + +variable {f g : E → F} {pf pg : FormalMultilinearSeries 𝕜 E F} {s : Set E} {x : E} {r : ℝ≥0∞} + +theorem HasFPowerSeriesWithinOnBall.add (hf : HasFPowerSeriesWithinOnBall f pf s x r) + (hg : HasFPowerSeriesWithinOnBall g pg s x r) : + HasFPowerSeriesWithinOnBall (f + g) (pf + pg) s x r := + { r_le := le_trans (le_min_iff.2 ⟨hf.r_le, hg.r_le⟩) (pf.min_radius_le_radius_add pg) + r_pos := hf.r_pos + hasSum := fun hy h'y => (hf.hasSum hy h'y).add (hg.hasSum hy h'y) } + +theorem HasFPowerSeriesOnBall.add (hf : HasFPowerSeriesOnBall f pf x r) + (hg : HasFPowerSeriesOnBall g pg x r) : HasFPowerSeriesOnBall (f + g) (pf + pg) x r := + { r_le := le_trans (le_min_iff.2 ⟨hf.r_le, hg.r_le⟩) (pf.min_radius_le_radius_add pg) + r_pos := hf.r_pos + hasSum := fun hy => (hf.hasSum hy).add (hg.hasSum hy) } + +theorem HasFPowerSeriesWithinAt.add + (hf : HasFPowerSeriesWithinAt f pf s x) (hg : HasFPowerSeriesWithinAt g pg s x) : + HasFPowerSeriesWithinAt (f + g) (pf + pg) s x := by + rcases (hf.eventually.and hg.eventually).exists with ⟨r, hr⟩ + exact ⟨r, hr.1.add hr.2⟩ + +theorem HasFPowerSeriesAt.add (hf : HasFPowerSeriesAt f pf x) (hg : HasFPowerSeriesAt g pg x) : + HasFPowerSeriesAt (f + g) (pf + pg) x := by + rcases (hf.eventually.and hg.eventually).exists with ⟨r, hr⟩ + exact ⟨r, hr.1.add hr.2⟩ + +theorem AnalyticWithinAt.add (hf : AnalyticWithinAt 𝕜 f s x) (hg : AnalyticWithinAt 𝕜 g s x) : + AnalyticWithinAt 𝕜 (f + g) s x := + let ⟨_, hpf⟩ := hf + let ⟨_, hqf⟩ := hg + (hpf.add hqf).analyticWithinAt + +theorem AnalyticAt.add (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : AnalyticAt 𝕜 (f + g) x := + let ⟨_, hpf⟩ := hf + let ⟨_, hqf⟩ := hg + (hpf.add hqf).analyticAt + +theorem HasFPowerSeriesWithinOnBall.neg (hf : HasFPowerSeriesWithinOnBall f pf s x r) : + HasFPowerSeriesWithinOnBall (-f) (-pf) s x r := + { r_le := by + rw [pf.radius_neg] + exact hf.r_le + r_pos := hf.r_pos + hasSum := fun hy h'y => (hf.hasSum hy h'y).neg } + +theorem HasFPowerSeriesOnBall.neg (hf : HasFPowerSeriesOnBall f pf x r) : + HasFPowerSeriesOnBall (-f) (-pf) x r := + { r_le := by + rw [pf.radius_neg] + exact hf.r_le + r_pos := hf.r_pos + hasSum := fun hy => (hf.hasSum hy).neg } + +theorem HasFPowerSeriesWithinAt.neg (hf : HasFPowerSeriesWithinAt f pf s x) : + HasFPowerSeriesWithinAt (-f) (-pf) s x := + let ⟨_, hrf⟩ := hf + hrf.neg.hasFPowerSeriesWithinAt + +theorem HasFPowerSeriesAt.neg (hf : HasFPowerSeriesAt f pf x) : HasFPowerSeriesAt (-f) (-pf) x := + let ⟨_, hrf⟩ := hf + hrf.neg.hasFPowerSeriesAt + +theorem AnalyticWithinAt.neg (hf : AnalyticWithinAt 𝕜 f s x) : AnalyticWithinAt 𝕜 (-f) s x := + let ⟨_, hpf⟩ := hf + hpf.neg.analyticWithinAt + +theorem AnalyticAt.neg (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (-f) x := + let ⟨_, hpf⟩ := hf + hpf.neg.analyticAt + +theorem HasFPowerSeriesWithinOnBall.sub (hf : HasFPowerSeriesWithinOnBall f pf s x r) + (hg : HasFPowerSeriesWithinOnBall g pg s x r) : + HasFPowerSeriesWithinOnBall (f - g) (pf - pg) s x r := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem HasFPowerSeriesOnBall.sub (hf : HasFPowerSeriesOnBall f pf x r) + (hg : HasFPowerSeriesOnBall g pg x r) : HasFPowerSeriesOnBall (f - g) (pf - pg) x r := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem HasFPowerSeriesWithinAt.sub + (hf : HasFPowerSeriesWithinAt f pf s x) (hg : HasFPowerSeriesWithinAt g pg s x) : + HasFPowerSeriesWithinAt (f - g) (pf - pg) s x := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem HasFPowerSeriesAt.sub (hf : HasFPowerSeriesAt f pf x) (hg : HasFPowerSeriesAt g pg x) : + HasFPowerSeriesAt (f - g) (pf - pg) x := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem AnalyticWithinAt.sub (hf : AnalyticWithinAt 𝕜 f s x) (hg : AnalyticWithinAt 𝕜 g s x) : + AnalyticWithinAt 𝕜 (f - g) s x := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem AnalyticAt.sub (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : + AnalyticAt 𝕜 (f - g) x := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem AnalyticWithinOn.add (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : + AnalyticWithinOn 𝕜 (f + g) s := + fun z hz => (hf z hz).add (hg z hz) + +theorem AnalyticOn.add (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : + AnalyticOn 𝕜 (f + g) s := + fun z hz => (hf z hz).add (hg z hz) + +theorem AnalyticWithinOn.neg (hf : AnalyticWithinOn 𝕜 f s) : AnalyticWithinOn 𝕜 (-f) s := + fun z hz ↦ (hf z hz).neg + +theorem AnalyticOn.neg (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (-f) s := + fun z hz ↦ (hf z hz).neg + +theorem AnalyticWithinOn.sub (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : + AnalyticWithinOn 𝕜 (f - g) s := + fun z hz => (hf z hz).sub (hg z hz) + +theorem AnalyticOn.sub (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : + AnalyticOn 𝕜 (f - g) s := + fun z hz => (hf z hz).sub (hg z hz) + +end + /-! ### Cartesian products are analytic -/ diff --git a/Mathlib/Analysis/Analytic/Uniqueness.lean b/Mathlib/Analysis/Analytic/Uniqueness.lean index d626ccca6a55a..088cf07ea867d 100644 --- a/Mathlib/Analysis/Analytic/Uniqueness.lean +++ b/Mathlib/Analysis/Analytic/Uniqueness.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Analytic.Linear import Mathlib.Analysis.Analytic.Composition +import Mathlib.Analysis.Analytic.Constructions import Mathlib.Analysis.Normed.Module.Completion import Mathlib.Analysis.Analytic.ChangeOrigin @@ -21,7 +22,137 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom open Set -open scoped Topology ENNReal +open scoped Topology ENNReal NNReal + +/-! +### Uniqueness of power series +If a function `f : E → F` has two representations as power series at a point `x : E`, corresponding +to formal multilinear series `p₁` and `p₂`, then these representations agree term-by-term. That is, +for any `n : ℕ` and `y : E`, `p₁ n (fun i ↦ y) = p₂ n (fun i ↦ y)`. In the one-dimensional case, +when `f : 𝕜 → E`, the continuous multilinear maps `p₁ n` and `p₂ n` are given by +`ContinuousMultilinearMap.mkPiRing`, and hence are determined completely by the value of +`p₁ n (fun i ↦ 1)`, so `p₁ = p₂`. Consequently, the radius of convergence for one series can be +transferred to the other. +-/ + +section Uniqueness + +open ContinuousMultilinearMap + +theorem Asymptotics.IsBigO.continuousMultilinearMap_apply_eq_zero {n : ℕ} {p : E[×n]→L[𝕜] F} + (h : (fun y => p fun _ => y) =O[𝓝 0] fun y => ‖y‖ ^ (n + 1)) (y : E) : (p fun _ => y) = 0 := by + obtain ⟨c, c_pos, hc⟩ := h.exists_pos + obtain ⟨t, ht, t_open, z_mem⟩ := eventually_nhds_iff.mp (isBigOWith_iff.mp hc) + obtain ⟨δ, δ_pos, δε⟩ := (Metric.isOpen_iff.mp t_open) 0 z_mem + clear h hc z_mem + cases' n with n + · exact norm_eq_zero.mp (by + -- Porting note: the symmetric difference of the `simpa only` sets: + -- added `zero_add, pow_one` + -- removed `zero_pow, Ne.def, Nat.one_ne_zero, not_false_iff` + simpa only [fin0_apply_norm, norm_eq_zero, norm_zero, zero_add, pow_one, + mul_zero, norm_le_zero_iff] using ht 0 (δε (Metric.mem_ball_self δ_pos))) + · refine Or.elim (Classical.em (y = 0)) + (fun hy => by simpa only [hy] using p.map_zero) fun hy => ?_ + replace hy := norm_pos_iff.mpr hy + refine norm_eq_zero.mp (le_antisymm (le_of_forall_pos_le_add fun ε ε_pos => ?_) (norm_nonneg _)) + have h₀ := _root_.mul_pos c_pos (pow_pos hy (n.succ + 1)) + obtain ⟨k, k_pos, k_norm⟩ := NormedField.exists_norm_lt 𝕜 + (lt_min (mul_pos δ_pos (inv_pos.mpr hy)) (mul_pos ε_pos (inv_pos.mpr h₀))) + have h₁ : ‖k • y‖ < δ := by + rw [norm_smul] + exact inv_mul_cancel_right₀ hy.ne.symm δ ▸ + mul_lt_mul_of_pos_right (lt_of_lt_of_le k_norm (min_le_left _ _)) hy + have h₂ := + calc + ‖p fun _ => k • y‖ ≤ c * ‖k • y‖ ^ (n.succ + 1) := by + -- Porting note: now Lean wants `_root_.` + simpa only [norm_pow, _root_.norm_norm] using ht (k • y) (δε (mem_ball_zero_iff.mpr h₁)) + --simpa only [norm_pow, norm_norm] using ht (k • y) (δε (mem_ball_zero_iff.mpr h₁)) + _ = ‖k‖ ^ n.succ * (‖k‖ * (c * ‖y‖ ^ (n.succ + 1))) := by + -- Porting note: added `Nat.succ_eq_add_one` since otherwise `ring` does not conclude. + simp only [norm_smul, mul_pow, Nat.succ_eq_add_one] + -- Porting note: removed `rw [pow_succ]`, since it now becomes superfluous. + ring + have h₃ : ‖k‖ * (c * ‖y‖ ^ (n.succ + 1)) < ε := + inv_mul_cancel_right₀ h₀.ne.symm ε ▸ + mul_lt_mul_of_pos_right (lt_of_lt_of_le k_norm (min_le_right _ _)) h₀ + calc + ‖p fun _ => y‖ = ‖k⁻¹ ^ n.succ‖ * ‖p fun _ => k • y‖ := by + simpa only [inv_smul_smul₀ (norm_pos_iff.mp k_pos), norm_smul, Finset.prod_const, + Finset.card_fin] using + congr_arg norm (p.map_smul_univ (fun _ : Fin n.succ => k⁻¹) fun _ : Fin n.succ => k • y) + _ ≤ ‖k⁻¹ ^ n.succ‖ * (‖k‖ ^ n.succ * (‖k‖ * (c * ‖y‖ ^ (n.succ + 1)))) := by gcongr + _ = ‖(k⁻¹ * k) ^ n.succ‖ * (‖k‖ * (c * ‖y‖ ^ (n.succ + 1))) := by + rw [← mul_assoc] + simp [norm_mul, mul_pow] + _ ≤ 0 + ε := by + rw [inv_mul_cancel₀ (norm_pos_iff.mp k_pos)] + simpa using h₃.le + +/-- If a formal multilinear series `p` represents the zero function at `x : E`, then the +terms `p n (fun i ↦ y)` appearing in the sum are zero for any `n : ℕ`, `y : E`. -/ +theorem HasFPowerSeriesAt.apply_eq_zero {p : FormalMultilinearSeries 𝕜 E F} {x : E} + (h : HasFPowerSeriesAt 0 p x) (n : ℕ) : ∀ y : E, (p n fun _ => y) = 0 := by + refine Nat.strong_induction_on n fun k hk => ?_ + have psum_eq : p.partialSum (k + 1) = fun y => p k fun _ => y := by + funext z + refine Finset.sum_eq_single _ (fun b hb hnb => ?_) fun hn => ?_ + · have := Finset.mem_range_succ_iff.mp hb + simp only [hk b (this.lt_of_ne hnb), Pi.zero_apply] + · exact False.elim (hn (Finset.mem_range.mpr (lt_add_one k))) + replace h := h.isBigO_sub_partialSum_pow k.succ + simp only [psum_eq, zero_sub, Pi.zero_apply, Asymptotics.isBigO_neg_left] at h + exact h.continuousMultilinearMap_apply_eq_zero + +/-- A one-dimensional formal multilinear series representing the zero function is zero. -/ +theorem HasFPowerSeriesAt.eq_zero {p : FormalMultilinearSeries 𝕜 𝕜 E} {x : 𝕜} + (h : HasFPowerSeriesAt 0 p x) : p = 0 := by + ext n x + rw [← mkPiRing_apply_one_eq_self (p n)] + simp [h.apply_eq_zero n 1] + +/-- One-dimensional formal multilinear series representing the same function are equal. -/ +theorem HasFPowerSeriesAt.eq_formalMultilinearSeries {p₁ p₂ : FormalMultilinearSeries 𝕜 𝕜 E} + {f : 𝕜 → E} {x : 𝕜} (h₁ : HasFPowerSeriesAt f p₁ x) (h₂ : HasFPowerSeriesAt f p₂ x) : p₁ = p₂ := + sub_eq_zero.mp (HasFPowerSeriesAt.eq_zero (x := x) (by simpa only [sub_self] using h₁.sub h₂)) + +theorem HasFPowerSeriesAt.eq_formalMultilinearSeries_of_eventually + {p q : FormalMultilinearSeries 𝕜 𝕜 E} {f g : 𝕜 → E} {x : 𝕜} (hp : HasFPowerSeriesAt f p x) + (hq : HasFPowerSeriesAt g q x) (heq : ∀ᶠ z in 𝓝 x, f z = g z) : p = q := + (hp.congr heq).eq_formalMultilinearSeries hq + +/-- A one-dimensional formal multilinear series representing a locally zero function is zero. -/ +theorem HasFPowerSeriesAt.eq_zero_of_eventually {p : FormalMultilinearSeries 𝕜 𝕜 E} {f : 𝕜 → E} + {x : 𝕜} (hp : HasFPowerSeriesAt f p x) (hf : f =ᶠ[𝓝 x] 0) : p = 0 := + (hp.congr hf).eq_zero + +/-- If a function `f : 𝕜 → E` has two power series representations at `x`, then the given radii in +which convergence is guaranteed may be interchanged. This can be useful when the formal multilinear +series in one representation has a particularly nice form, but the other has a larger radius. -/ +theorem HasFPowerSeriesOnBall.exchange_radius {p₁ p₂ : FormalMultilinearSeries 𝕜 𝕜 E} {f : 𝕜 → E} + {r₁ r₂ : ℝ≥0∞} {x : 𝕜} (h₁ : HasFPowerSeriesOnBall f p₁ x r₁) + (h₂ : HasFPowerSeriesOnBall f p₂ x r₂) : HasFPowerSeriesOnBall f p₁ x r₂ := + h₂.hasFPowerSeriesAt.eq_formalMultilinearSeries h₁.hasFPowerSeriesAt ▸ h₂ + +/-- If a function `f : 𝕜 → E` has power series representation `p` on a ball of some radius and for +each positive radius it has some power series representation, then `p` converges to `f` on the whole +`𝕜`. -/ +theorem HasFPowerSeriesOnBall.r_eq_top_of_exists {f : 𝕜 → E} {r : ℝ≥0∞} {x : 𝕜} + {p : FormalMultilinearSeries 𝕜 𝕜 E} (h : HasFPowerSeriesOnBall f p x r) + (h' : ∀ (r' : ℝ≥0) (_ : 0 < r'), ∃ p' : FormalMultilinearSeries 𝕜 𝕜 E, + HasFPowerSeriesOnBall f p' x r') : + HasFPowerSeriesOnBall f p x ∞ := + { r_le := ENNReal.le_of_forall_pos_nnreal_lt fun r hr _ => + let ⟨_, hp'⟩ := h' r hr + (h.exchange_radius hp').r_le + r_pos := ENNReal.coe_lt_top + hasSum := fun {y} _ => + let ⟨r', hr'⟩ := exists_gt ‖y‖₊ + let ⟨_, hp'⟩ := h' r' hr'.ne_bot.bot_lt + (h.exchange_radius hp').hasSum <| mem_emetric_ball_zero_iff.mpr (ENNReal.coe_lt_coe.2 hr') } + +end Uniqueness namespace AnalyticOn diff --git a/Mathlib/Analysis/Analytic/Within.lean b/Mathlib/Analysis/Analytic/Within.lean index 9c2d765aaf5fd..7b1093877a659 100644 --- a/Mathlib/Analysis/Analytic/Within.lean +++ b/Mathlib/Analysis/Analytic/Within.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Geoffrey Irving. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Geoffrey Irving -/ -import Mathlib.Analysis.Calculus.FDeriv.Analytic +import Mathlib.Analysis.Analytic.Constructions /-! # Properties of analyticity restricted to a set @@ -14,12 +14,10 @@ From `Mathlib.Analysis.Analytic.Basic`, we have the definitions 2. `AnalyticWithinOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. This means there exists an extension of `f` which is analytic and agrees with `f` on `s ∪ {x}`, but -`f` is allowed to be arbitrary elsewhere. Requiring `ContinuousWithinAt` is essential if `x ∉ s`: -it is required for composition and smoothness to follow without extra hypotheses (we could -alternately require convergence at `x` even if `x ∉ s`). +`f` is allowed to be arbitrary elsewhere. Here we prove basic properties of these definitions. Where convenient we assume completeness of the -ambient space, which allows us to related `AnalyticWithinAt` to analyticity of a local extension. +ambient space, which allows us to relate `AnalyticWithinAt` to analyticity of a local extension. -/ noncomputable section @@ -58,10 +56,6 @@ lemma analyticWithinAt_of_singleton_mem {f : E → F} {s : Set E} {x : E} (h : { apply (hasFPowerSeriesOnBall_const (e := 0)).hasSum simp only [Metric.emetric_ball_top, mem_univ] }⟩ -lemma AnalyticWithinOn.continuousOn {f : E → F} {s : Set E} (h : AnalyticWithinOn 𝕜 f s) : - ContinuousOn f s := - fun x m ↦ (h x m).continuousWithinAt - /-- If `f` is `AnalyticWithinOn` near each point in a set, it is `AnalyticWithinOn` the set -/ lemma analyticWithinOn_of_locally_analyticWithinOn {f : E → F} {s : Set E} (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ AnalyticWithinOn 𝕜 f (s ∩ u)) : @@ -200,74 +194,3 @@ lemma analyticWithinAt_iff_exists_analyticAt' [CompleteSpace F] {f : E → F} {s exact ⟨g, by filter_upwards [self_mem_nhdsWithin] using hf, hg⟩ alias ⟨AnalyticWithinAt.exists_analyticAt, _⟩ := analyticWithinAt_iff_exists_analyticAt' - -/-! -### Congruence - --/ - - -lemma HasFPowerSeriesWithinOnBall.congr {f g : E → F} {p : FormalMultilinearSeries 𝕜 E F} - {s : Set E} {x : E} {r : ℝ≥0∞} (h : HasFPowerSeriesWithinOnBall f p s x r) - (h' : EqOn g f (s ∩ EMetric.ball x r)) (h'' : g x = f x) : - HasFPowerSeriesWithinOnBall g p s x r := by - refine ⟨h.r_le, h.r_pos, ?_⟩ - · intro y hy h'y - convert h.hasSum hy h'y using 1 - simp only [mem_insert_iff, add_right_eq_self] at hy - rcases hy with rfl | hy - · simpa using h'' - · apply h' - refine ⟨hy, ?_⟩ - simpa [edist_eq_coe_nnnorm_sub] using h'y - -lemma HasFPowerSeriesWithinAt.congr {f g : E → F} {p : FormalMultilinearSeries 𝕜 E F} {s : Set E} - {x : E} (h : HasFPowerSeriesWithinAt f p s x) (h' : g =ᶠ[𝓝[s] x] f) (h'' : g x = f x) : - HasFPowerSeriesWithinAt g p s x := by - rcases h with ⟨r, hr⟩ - obtain ⟨ε, εpos, hε⟩ : ∃ ε > 0, EMetric.ball x ε ∩ s ⊆ {y | g y = f y} := - EMetric.mem_nhdsWithin_iff.1 h' - let r' := min r ε - refine ⟨r', ?_⟩ - have := hr.of_le (r' := r') (by simp [r', εpos, hr.r_pos]) (min_le_left _ _) - apply this.congr _ h'' - intro z hz - exact hε ⟨EMetric.ball_subset_ball (min_le_right _ _) hz.2, hz.1⟩ - - -lemma AnalyticWithinAt.congr_of_eventuallyEq {f g : E → F} {s : Set E} {x : E} - (hf : AnalyticWithinAt 𝕜 f s x) (hs : g =ᶠ[𝓝[s] x] f) (hx : g x = f x) : - AnalyticWithinAt 𝕜 g s x := by - rcases hf with ⟨p, hp⟩ - exact ⟨p, hp.congr hs hx⟩ - -lemma AnalyticWithinAt.congr {f g : E → F} {s : Set E} {x : E} - (hf : AnalyticWithinAt 𝕜 f s x) (hs : EqOn g f s) (hx : g x = f x) : - AnalyticWithinAt 𝕜 g s x := - hf.congr_of_eventuallyEq hs.eventuallyEq_nhdsWithin hx - -lemma AnalyticWithinOn.congr {f g : E → F} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hs : EqOn g f s) : - AnalyticWithinOn 𝕜 g s := - fun x m ↦ (hf x m).congr hs (hs m) - -/-! -### Monotonicity w.r.t. the set we're analytic within --/ - -lemma AnalyticWithinOn.mono {f : E → F} {s t : Set E} (h : AnalyticWithinOn 𝕜 f t) - (hs : s ⊆ t) : AnalyticWithinOn 𝕜 f s := - fun _ m ↦ (h _ (hs m)).mono hs - -/-! -### Analyticity within implies smoothness --/ - -lemma AnalyticWithinAt.contDiffWithinAt [CompleteSpace F] {f : E → F} {s : Set E} {x : E} - (h : AnalyticWithinAt 𝕜 f s x) {n : ℕ∞} : ContDiffWithinAt 𝕜 n f s x := by - rcases h.exists_analyticAt with ⟨g, fx, fg, hg⟩ - exact hg.contDiffAt.contDiffWithinAt.congr (fg.mono (subset_insert _ _)) fx - -lemma AnalyticWithinOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E} - (h : AnalyticWithinOn 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := - fun x m ↦ (h x m).contDiffWithinAt diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 2a73636d97065..328fdab8161af 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Analysis.Analytic.Basic import Mathlib.Analysis.Analytic.CPolynomial +import Mathlib.Analysis.Analytic.Within import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.Calculus.ContDiff.Defs import Mathlib.Analysis.Calculus.FDeriv.Add @@ -19,7 +19,7 @@ As an application, we show that continuous multilinear maps are smooth. We also iterated derivatives, in `ContinuousMultilinearMap.iteratedFDeriv_eq`. -/ -open Filter Asymptotics +open Filter Asymptotics Set open scoped ENNReal @@ -127,6 +127,15 @@ theorem AnalyticAt.contDiffAt [CompleteSpace F] (h : AnalyticAt 𝕜 f x) {n : obtain ⟨s, hs, hf⟩ := h.exists_mem_nhds_analyticOn exact hf.contDiffOn.contDiffAt hs +lemma AnalyticWithinAt.contDiffWithinAt [CompleteSpace F] {f : E → F} {s : Set E} {x : E} + (h : AnalyticWithinAt 𝕜 f s x) {n : ℕ∞} : ContDiffWithinAt 𝕜 n f s x := by + rcases h.exists_analyticAt with ⟨g, fx, fg, hg⟩ + exact hg.contDiffAt.contDiffWithinAt.congr (fg.mono (subset_insert _ _)) fx + +lemma AnalyticWithinOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E} + (h : AnalyticWithinOn 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := + fun x m ↦ (h x m).contDiffWithinAt + end fderiv section deriv @@ -306,7 +315,7 @@ theorem changeOrigin_toFormalMultilinearSeries [DecidableEq ι] : refine (Fintype.sum_bijective (?_ ∘ Fintype.equivFinOfCardEq (Nat.add_sub_of_le Fintype.card_pos).symm) (.comp ?_ <| Equiv.bijective _) _ _ fun i ↦ ?_).symm · exact (⟨{·}ᶜ, by - rw [card_compl, Fintype.card_fin, card_singleton, Nat.add_sub_cancel_left]⟩) + rw [card_compl, Fintype.card_fin, Finset.card_singleton, Nat.add_sub_cancel_left]⟩) · use fun _ _ ↦ (singleton_injective <| compl_injective <| Subtype.ext_iff.mp ·) intro ⟨s, hs⟩ have h : sᶜ.card = 1 := by rw [card_compl, hs, Fintype.card_fin, Nat.add_sub_cancel] diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index 34b6b1a9cb845..acb07715c395f 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ +import Mathlib.Analysis.Analytic.Uniqueness import Mathlib.Analysis.Calculus.DiffContOnCl import Mathlib.Analysis.Calculus.Dslope import Mathlib.Analysis.Calculus.FDeriv.Analytic diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index 7ee428de68337..442b24423f19a 100644 --- a/Mathlib/Geometry/Manifold/AnalyticManifold.lean +++ b/Mathlib/Geometry/Manifold/AnalyticManifold.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Lee, Geoffrey Irving -/ import Mathlib.Analysis.Analytic.Constructions -import Mathlib.Analysis.Analytic.Within +import Mathlib.Analysis.Calculus.FDeriv.Analytic import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners /-! From f8da9a58a293d85c57d96f9c04cd8dde3760e5a4 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Fri, 20 Sep 2024 18:56:41 +0000 Subject: [PATCH 069/170] feat(Order/Group): add `zpow_right_strictAnti` (#16937) Also use it to golf `Subgroup.mem_closure_singleton_iff_existsUnique_zpow`. --- Mathlib/Algebra/Order/Group/Basic.lean | 11 +++++++- Mathlib/Algebra/Order/ToIntervalMod.lean | 6 ++--- Mathlib/GroupTheory/ArchimedeanDensely.lean | 28 +++++++------------- Mathlib/MeasureTheory/Integral/Periodic.lean | 4 +-- Mathlib/Topology/Instances/AddCircle.lean | 2 +- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Mathlib/Algebra/Order/Group/Basic.lean b/Mathlib/Algebra/Order/Group/Basic.lean index 449dd1fe025dc..9c07d497a0c75 100644 --- a/Mathlib/Algebra/Order/Group/Basic.lean +++ b/Mathlib/Algebra/Order/Group/Basic.lean @@ -27,13 +27,22 @@ variable [OrderedCommGroup α] {m n : ℤ} {a b : α} rintro rfl simp at hn -@[to_additive zsmul_strictMono_left] +@[to_additive zsmul_left_strictMono] lemma zpow_right_strictMono (ha : 1 < a) : StrictMono fun n : ℤ ↦ a ^ n := fun m n h ↦ calc a ^ m = a ^ m * 1 := (mul_one _).symm _ < a ^ m * a ^ (n - m) := mul_lt_mul_left' (one_lt_zpow' ha <| Int.sub_pos_of_lt h) _ _ = a ^ n := by simp [← zpow_add, m.add_comm] +@[deprecated (since := "2024-09-19")] alias zsmul_strictMono_left := zsmul_left_strictMono + +@[to_additive zsmul_left_strictAnti] +lemma zpow_right_strictAnti (ha : a < 1) : StrictAnti fun n : ℤ ↦ a ^ n := fun m n h ↦ calc + a ^ n < a ^ n * a⁻¹ ^ (n - m) := + lt_mul_of_one_lt_right' _ <| one_lt_zpow' (one_lt_inv'.2 ha) <| Int.sub_pos.2 h + _ = a ^ m := by + rw [inv_zpow', Int.neg_sub, ← zpow_add, Int.add_comm, Int.sub_add_cancel] + @[to_additive zsmul_left_inj] lemma zpow_right_inj (ha : 1 < a) {m n : ℤ} : a ^ m = a ^ n ↔ m = n := (zpow_right_strictMono ha).injective.eq_iff diff --git a/Mathlib/Algebra/Order/ToIntervalMod.lean b/Mathlib/Algebra/Order/ToIntervalMod.lean index 938027eaa347f..686d38e4a5a1b 100644 --- a/Mathlib/Algebra/Order/ToIntervalMod.lean +++ b/Mathlib/Algebra/Order/ToIntervalMod.lean @@ -557,12 +557,12 @@ theorem not_modEq_iff_toIcoMod_eq_toIocMod : ¬a ≡ b [PMOD p] ↔ toIcoMod hp theorem not_modEq_iff_toIcoDiv_eq_toIocDiv : ¬a ≡ b [PMOD p] ↔ toIcoDiv hp a b = toIocDiv hp a b := by rw [not_modEq_iff_toIcoMod_eq_toIocMod hp, toIcoMod, toIocMod, sub_right_inj, - (zsmul_strictMono_left hp).injective.eq_iff] + zsmul_left_inj hp] theorem modEq_iff_toIcoDiv_eq_toIocDiv_add_one : a ≡ b [PMOD p] ↔ toIcoDiv hp a b = toIocDiv hp a b + 1 := by rw [modEq_iff_toIcoMod_add_period_eq_toIocMod hp, toIcoMod, toIocMod, ← eq_sub_iff_add_eq, - sub_sub, sub_right_inj, ← add_one_zsmul, (zsmul_strictMono_left hp).injective.eq_iff] + sub_sub, sub_right_inj, ← add_one_zsmul, zsmul_left_inj hp] end AddCommGroup @@ -595,7 +595,7 @@ theorem toIcoMod_le_toIocMod (a b : α) : toIcoMod hp a b ≤ toIocMod hp a b := theorem toIocMod_le_toIcoMod_add (a b : α) : toIocMod hp a b ≤ toIcoMod hp a b + p := by rw [toIcoMod, toIocMod, sub_add, sub_le_sub_iff_left, sub_le_iff_le_add, ← add_one_zsmul, - (zsmul_strictMono_left hp).le_iff_le] + (zsmul_left_strictMono hp).le_iff_le] apply (toIocDiv_wcovBy_toIcoDiv _ _ _).le_succ end IcoIoc diff --git a/Mathlib/GroupTheory/ArchimedeanDensely.lean b/Mathlib/GroupTheory/ArchimedeanDensely.lean index dddf5efd91a55..7058cf4ed386d 100644 --- a/Mathlib/GroupTheory/ArchimedeanDensely.lean +++ b/Mathlib/GroupTheory/ArchimedeanDensely.lean @@ -34,25 +34,15 @@ This is the stronger version of `AddSubgroup.mem_closure_singleton`."] lemma Subgroup.mem_closure_singleton_iff_existsUnique_zpow {G : Type*} [LinearOrderedCommGroup G] {a b : G} (ha : a ≠ 1) : b ∈ closure {a} ↔ ∃! k : ℤ, a ^ k = b := by - constructor <;> intro h - · wlog ha : 1 < a generalizing a b - · simp only [not_lt] at ha - rcases ha.eq_or_lt with rfl|ha - · contradiction - specialize @this a⁻¹ b (by simpa) (by simpa) (by simpa) - simp only [inv_zpow'] at this - obtain ⟨k, rfl, hk'⟩ := this - refine ⟨-k, rfl, ?_⟩ - intro y hy - rw [← neg_eq_iff_eq_neg] - exact hk' _ (by simpa using hy) - · rw [mem_closure_singleton] at h - obtain ⟨k, hk⟩ := h - refine ⟨k, hk, ?_⟩ - rintro l rfl - rwa [← zpow_right_inj ha, eq_comm] - · rw [mem_closure_singleton] - exact h.exists + rw [mem_closure_singleton] + constructor + · suffices Function.Injective (a ^ · : ℤ → G) by + rintro ⟨m, rfl⟩ + exact ⟨m, rfl, fun k hk ↦ this hk⟩ + rcases ha.lt_or_lt with ha | ha + · exact (zpow_right_strictAnti ha).injective + · exact (zpow_right_strictMono ha).injective + · exact fun h ↦ h.exists open Subgroup in /-- In two linearly ordered groups, the closure of an element of one group diff --git a/Mathlib/MeasureTheory/Integral/Periodic.lean b/Mathlib/MeasureTheory/Integral/Periodic.lean index a29b25d9ed321..c86458b3ee841 100644 --- a/Mathlib/MeasureTheory/Integral/Periodic.lean +++ b/Mathlib/MeasureTheory/Integral/Periodic.lean @@ -37,7 +37,7 @@ theorem isAddFundamentalDomain_Ioc {T : ℝ} (hT : 0 < T) (t : ℝ) IsAddFundamentalDomain (AddSubgroup.zmultiples T) (Ioc t (t + T)) μ := by refine IsAddFundamentalDomain.mk' nullMeasurableSet_Ioc fun x => ?_ have : Bijective (codRestrict (fun n : ℤ => n • T) (AddSubgroup.zmultiples T) _) := - (Equiv.ofInjective (fun n : ℤ => n • T) (zsmul_strictMono_left hT).injective).bijective + (Equiv.ofInjective (fun n : ℤ => n • T) (zsmul_left_strictMono hT).injective).bijective refine this.existsUnique_iff.2 ?_ simpa only [add_comm x] using existsUnique_add_zsmul_mem_Ioc hT x t @@ -45,7 +45,7 @@ theorem isAddFundamentalDomain_Ioc' {T : ℝ} (hT : 0 < T) (t : ℝ) (μ : Measu IsAddFundamentalDomain (AddSubgroup.op <| .zmultiples T) (Ioc t (t + T)) μ := by refine IsAddFundamentalDomain.mk' nullMeasurableSet_Ioc fun x => ?_ have : Bijective (codRestrict (fun n : ℤ => n • T) (AddSubgroup.zmultiples T) _) := - (Equiv.ofInjective (fun n : ℤ => n • T) (zsmul_strictMono_left hT).injective).bijective + (Equiv.ofInjective (fun n : ℤ => n • T) (zsmul_left_strictMono hT).injective).bijective refine (AddSubgroup.equivOp _).bijective.comp this |>.existsUnique_iff.2 ?_ simpa using existsUnique_add_zsmul_mem_Ioc hT x t diff --git a/Mathlib/Topology/Instances/AddCircle.lean b/Mathlib/Topology/Instances/AddCircle.lean index 30a63f58660fd..3295ee564f992 100644 --- a/Mathlib/Topology/Instances/AddCircle.lean +++ b/Mathlib/Topology/Instances/AddCircle.lean @@ -461,7 +461,7 @@ def setAddOrderOfEquiv {n : ℕ} (hn : 0 < n) : obtain ⟨m, hm⟩ := h rw [← mul_div_right_comm, eq_div_iff, mul_comm, ← zsmul_eq_mul, mul_smul_comm, ← nsmul_eq_mul, ← natCast_zsmul, smul_smul, - (zsmul_strictMono_left hp.out).injective.eq_iff, mul_comm] at hm + zsmul_left_inj hp.out, mul_comm] at hm swap · exact Nat.cast_ne_zero.2 hn.ne' rw [← @Nat.cast_inj ℤ, ← sub_eq_zero] From 555be78e7f1df5d448c64e4282ece0dcc21214ff Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Fri, 20 Sep 2024 19:31:10 +0000 Subject: [PATCH 070/170] feat(Data/Finset): card_eq_succ in terms of cons (#16951) Also add `cons_ne_empty` and make it simp, also to match `insert_ne_empty` --- Mathlib/Data/Finset/Basic.lean | 2 ++ Mathlib/Data/Finset/Card.lean | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index 4be4579898b91..142100db3baa1 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -778,6 +778,8 @@ theorem cons_nonempty (h : a ∉ s) : (cons a s h).Nonempty := @[deprecated (since := "2024-09-19")] alias nonempty_cons := cons_nonempty +@[simp] theorem cons_ne_empty (h : a ∉ s) : cons a s h ≠ ∅ := (cons_nonempty _).ne_empty + @[simp] theorem nonempty_mk {m : Multiset α} {hm} : (⟨m, hm⟩ : Finset α).Nonempty ↔ m ≠ 0 := by induction m using Multiset.induction_on <;> simp diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index c143030e91559..1ec1dc95a10f2 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -683,6 +683,11 @@ lemma exists_of_one_lt_card_pi {ι : Type*} {α : ι → Type*} [∀ i, Decidabl obtain rfl | hne := eq_or_ne (a2 i) ai exacts [⟨a1, h1, hne⟩, ⟨a2, h2, hne⟩] +theorem card_eq_succ_iff_cons : + s.card = n + 1 ↔ ∃ a t, ∃ (h : a ∉ t), cons a t h = s ∧ t.card = n := + ⟨cons_induction_on s (by simp) fun a s _ _ _ => ⟨a, s, by simp_all⟩, + fun ⟨a, t, _, hs, _⟩ => by simpa [← hs]⟩ + section DecidableEq variable [DecidableEq α] From 795419690d6c83cf666e3854609a1a48d2156ba0 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Fri, 20 Sep 2024 20:19:10 +0000 Subject: [PATCH 071/170] chore(Tactic/GCongr): new file for `@[gcongr] leanInitLemma` (#16788) Also add some missing attrs. --- Mathlib.lean | 1 + .../Algebra/Order/GroupWithZero/Unbundled.lean | 2 +- Mathlib/Algebra/Order/Module/OrderedSMul.lean | 2 +- Mathlib/Analysis/Normed/Group/Seminorm.lean | 2 +- Mathlib/Data/Int/ModEq.lean | 2 +- Mathlib/Data/List/Infix.lean | 4 ---- Mathlib/Data/NNReal/Basic.lean | 2 +- Mathlib/Data/Nat/Defs.lean | 2 +- Mathlib/Data/Nat/Factorial/Basic.lean | 2 +- Mathlib/Order/Lattice.lean | 2 +- Mathlib/Tactic.lean | 1 + Mathlib/Tactic/GCongr.lean | 2 +- Mathlib/Tactic/GCongr/CoreAttrs.lean | 16 ++++++++++++++++ scripts/noshake.json | 2 +- 14 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 Mathlib/Tactic/GCongr/CoreAttrs.lean diff --git a/Mathlib.lean b/Mathlib.lean index 1dd73c2e11a79..9aac5382744a8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4229,6 +4229,7 @@ import Mathlib.Tactic.FunProp.ToBatteries import Mathlib.Tactic.FunProp.Types import Mathlib.Tactic.GCongr import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Tactic.GCongr.ForwardAttr import Mathlib.Tactic.Generalize import Mathlib.Tactic.GeneralizeProofs diff --git a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean index 9db3efba2f326..ce7ed361fd599 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Group.Pi.Basic import Mathlib.Algebra.GroupWithZero.Units.Basic import Mathlib.Algebra.Order.Monoid.Unbundled.Defs import Mathlib.Algebra.Order.ZeroLEOne -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Tactic.Nontriviality /-! diff --git a/Mathlib/Algebra/Order/Module/OrderedSMul.lean b/Mathlib/Algebra/Order/Module/OrderedSMul.lean index bf1439508f708..ff7892c724901 100644 --- a/Mathlib/Algebra/Order/Module/OrderedSMul.lean +++ b/Mathlib/Algebra/Order/Module/OrderedSMul.lean @@ -9,7 +9,7 @@ import Mathlib.Algebra.Module.Prod import Mathlib.Algebra.Order.Module.Defs import Mathlib.Algebra.Order.Monoid.Prod import Mathlib.Algebra.Order.Pi -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs /-! # Ordered scalar product diff --git a/Mathlib/Analysis/Normed/Group/Seminorm.lean b/Mathlib/Analysis/Normed/Group/Seminorm.lean index 39f1d2b490a43..ca8445c51637b 100644 --- a/Mathlib/Analysis/Normed/Group/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Group/Seminorm.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: María Inés de Frutos-Fernández, Yaël Dillies -/ import Mathlib.Data.NNReal.Basic -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs /-! # Group seminorms diff --git a/Mathlib/Data/Int/ModEq.lean b/Mathlib/Data/Int/ModEq.lean index bdd7e1559edbd..2f973a2e81d79 100644 --- a/Mathlib/Data/Int/ModEq.lean +++ b/Mathlib/Data/Int/ModEq.lean @@ -5,7 +5,7 @@ Authors: Chris Hughes -/ import Mathlib.Data.Nat.ModEq import Mathlib.Tactic.Abel -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs /-! diff --git a/Mathlib/Data/List/Infix.lean b/Mathlib/Data/List/Infix.lean index 4218035da5095..974beaac0fde7 100644 --- a/Mathlib/Data/List/Infix.lean +++ b/Mathlib/Data/List/Infix.lean @@ -63,8 +63,6 @@ lemma dropSlice_subset (n m : ℕ) (l : List α) : l.dropSlice n m ⊆ l := lemma mem_of_mem_dropSlice {n m : ℕ} {l : List α} {a : α} (h : a ∈ l.dropSlice n m) : a ∈ l := dropSlice_subset n m l h -attribute [gcongr] drop_sublist_drop_left - theorem tail_subset (l : List α) : tail l ⊆ l := (tail_sublist l).subset @@ -74,8 +72,6 @@ theorem mem_of_mem_dropLast (h : a ∈ l.dropLast) : a ∈ l := theorem mem_of_mem_tail (h : a ∈ l.tail) : a ∈ l := tail_subset l h -attribute [gcongr] Sublist.drop - theorem concat_get_prefix {x y : List α} (h : x <+: y) (hl : x.length < y.length) : x ++ [y.get ⟨x.length, hl⟩] <+: y := by use y.drop (x.length + 1) diff --git a/Mathlib/Data/NNReal/Basic.lean b/Mathlib/Data/NNReal/Basic.lean index c3165b2271890..df15ccc645e66 100644 --- a/Mathlib/Data/NNReal/Basic.lean +++ b/Mathlib/Data/NNReal/Basic.lean @@ -11,7 +11,7 @@ import Mathlib.Algebra.Order.Nonneg.Floor import Mathlib.Data.Real.Pointwise import Mathlib.Order.ConditionallyCompleteLattice.Group import Mathlib.Tactic.Bound.Attribute -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Algebra.Ring.Regular /-! diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean index dd38886b716c7..b5e07ed1bde05 100644 --- a/Mathlib/Data/Nat/Defs.lean +++ b/Mathlib/Data/Nat/Defs.lean @@ -5,7 +5,7 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Logic.Function.Basic import Mathlib.Logic.Nontrivial.Defs -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Tactic.PushNeg import Mathlib.Util.AssertExists diff --git a/Mathlib/Data/Nat/Factorial/Basic.lean b/Mathlib/Data/Nat/Factorial/Basic.lean index cacc9997b8c7e..79539c43a7625 100644 --- a/Mathlib/Data/Nat/Factorial/Basic.lean +++ b/Mathlib/Data/Nat/Factorial/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Chris Hughes, Floris van Doorn, Yaël Dillies -/ import Mathlib.Data.Nat.Defs -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Tactic.Common import Mathlib.Tactic.Monotonicity.Attr diff --git a/Mathlib/Order/Lattice.lean b/Mathlib/Order/Lattice.lean index 502fe4375dfb9..76070c79b4151 100644 --- a/Mathlib/Order/Lattice.lean +++ b/Mathlib/Order/Lattice.lean @@ -6,7 +6,7 @@ Authors: Johannes Hölzl import Mathlib.Data.Bool.Basic import Mathlib.Order.Monotone.Basic import Mathlib.Order.ULift -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs /-! # (Semi-)lattices diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index 5b0f01be92910..ce50b9c0db698 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -96,6 +96,7 @@ import Mathlib.Tactic.FunProp.ToBatteries import Mathlib.Tactic.FunProp.Types import Mathlib.Tactic.GCongr import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Tactic.GCongr.ForwardAttr import Mathlib.Tactic.Generalize import Mathlib.Tactic.GeneralizeProofs diff --git a/Mathlib/Tactic/GCongr.lean b/Mathlib/Tactic/GCongr.lean index dbee7afe65acd..ddb08c8e3e2dc 100644 --- a/Mathlib/Tactic/GCongr.lean +++ b/Mathlib/Tactic/GCongr.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Heather Macbeth -/ import Mathlib.Tactic.Positivity.Core -import Mathlib.Tactic.GCongr.Core +import Mathlib.Tactic.GCongr.CoreAttrs /-! # Setup for the `gcongr` tactic diff --git a/Mathlib/Tactic/GCongr/CoreAttrs.lean b/Mathlib/Tactic/GCongr/CoreAttrs.lean new file mode 100644 index 0000000000000..423dbda223088 --- /dev/null +++ b/Mathlib/Tactic/GCongr/CoreAttrs.lean @@ -0,0 +1,16 @@ +/- +Copyright (c) 2024 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Tactic.GCongr.Core + +/-! +# gcongr attributes for lemmas up in the import chain + +In this file we add `gcongr` attribute to lemmas in `Lean.Init`. +We may add lemmas from other files imported by `Mathlib/Tactic/GCongr/Core` later. +-/ + +attribute [gcongr] List.Sublist.append List.Sublist.append_left List.Sublist.append_right + List.Sublist.reverse List.drop_sublist_drop_left List.Sublist.drop Nat.succ_le_succ diff --git a/scripts/noshake.json b/scripts/noshake.json index f89111e03b279..f7776819fcd27 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -102,7 +102,7 @@ "Mathlib.Tactic.FinCases", "Mathlib.Tactic.Find", "Mathlib.Tactic.GCongr", - "Mathlib.Tactic.GCongr.Core", + "Mathlib.Tactic.GCongr.CoreAttrs", "Mathlib.Tactic.Generalize", "Mathlib.Tactic.GeneralizeProofs", "Mathlib.Tactic.Group", From 93c912ff3f53452ac03d33eafbc3d8be75d5ad45 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Sat, 21 Sep 2024 08:59:13 +0000 Subject: [PATCH 072/170] chore(Algebra/Basic): drop an unneeded instance (#16987) Deletions: - NoZeroSMulDivisors.Algebra.noZeroSMulDivisors This instance was weaker than `GroupWithZero.toNoZeroSMulDivisors`, see also [Zulip](https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/.E2.9C.94.20NoZeroSMulDivisors.2EAlgebra.2EnoZeroSMulDivisors) --- Mathlib/Algebra/Algebra/Basic.lean | 11 ----------- Mathlib/Algebra/Module/Basic.lean | 4 +--- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index 6b638c7aa5b45..29d91b4ab7439 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -314,17 +314,6 @@ instance (priority := 100) CharZero.noZeroSMulDivisors_int [Ring R] [NoZeroDivis [CharZero R] : NoZeroSMulDivisors ℤ R := NoZeroSMulDivisors.of_algebraMap_injective <| (algebraMap ℤ R).injective_int -section Field - -variable [Field R] [Semiring A] [Algebra R A] - --- see note [lower instance priority] -instance (priority := 100) Algebra.noZeroSMulDivisors [Nontrivial A] [NoZeroDivisors A] : - NoZeroSMulDivisors R A := - NoZeroSMulDivisors.of_algebraMap_injective (algebraMap R A).injective - -end Field - end NoZeroSMulDivisors section IsScalarTower diff --git a/Mathlib/Algebra/Module/Basic.lean b/Mathlib/Algebra/Module/Basic.lean index c8f18e8483148..8656e47667f24 100644 --- a/Mathlib/Algebra/Module/Basic.lean +++ b/Mathlib/Algebra/Module/Basic.lean @@ -101,9 +101,7 @@ section NoZeroSMulDivisors section Module -variable [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M] - -instance [NoZeroSMulDivisors ℤ M] : NoZeroSMulDivisors ℕ M := +instance [AddCommGroup M] [NoZeroSMulDivisors ℤ M] : NoZeroSMulDivisors ℕ M := ⟨fun {c x} hcx ↦ by rwa [← Nat.cast_smul_eq_nsmul ℤ c x, smul_eq_zero, Nat.cast_eq_zero] at hcx⟩ end Module From db728c79985195f4b64a2dd987ba4503861cd575 Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Sat, 21 Sep 2024 11:41:45 +0000 Subject: [PATCH 073/170] feat(CategoryTheory/Filtered): Finality of StructuredArrow.pre (#16728) --- .../CategoryTheory/Comma/StructuredArrow.lean | 67 +++++++++++++++++++ Mathlib/CategoryTheory/Limits/Final.lean | 24 +++++++ 2 files changed, 91 insertions(+) diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow.lean index 9dff431f80860..12b710e29af5b 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow.lean @@ -889,4 +889,71 @@ def costructuredArrowOpEquivalence (F : C ⥤ D) (d : D) : apply CommaMorphism.ext <;> dsimp [StructuredArrow.isoMk, StructuredArrow.homMk, Comma.isoMk]; simp +section Pre + +variable {E : Type u₃} [Category.{v₃} E] (F : C ⥤ D) {G : D ⥤ E} {e : E} + +/-- The functor establishing the equivalence `StructuredArrow.preEquivalence`. -/ +@[simps!] +def StructuredArrow.preEquivalence.functor (f : StructuredArrow e G) : + StructuredArrow f (pre e F G) ⥤ StructuredArrow f.right F where + obj g := mk g.hom.right + map φ := homMk φ.right.right <| by + have := w φ + simp only [Functor.const_obj_obj] at this ⊢ + rw [← this, comp_right] + simp + +/-- The inverse functor establishing the equivalence `StructuredArrow.preEquivalence`. -/ +@[simps!] +def StructuredArrow.preEquivalence.inverse (f : StructuredArrow e G) : + StructuredArrow f.right F ⥤ StructuredArrow f (pre e F G) where + obj g := mk + (Y := mk (Y := g.right) + (f.hom ≫ (G.map g.hom : G.obj f.right ⟶ (F ⋙ G).obj g.right))) + (homMk g.hom) + map φ := homMk <| homMk φ.right <| by + simp only [Functor.const_obj_obj, Functor.comp_obj, mk_right, mk_left, mk_hom_eq_self, + Functor.comp_map, Category.assoc, ← w φ, Functor.map_comp] + +/-- A structured arrow category on a `StructuredArrow.pre e F G` functor is equivalent to the +structured arrow category on F -/ +def StructuredArrow.preEquivalence (f : StructuredArrow e G) : + StructuredArrow f (pre e F G) ≌ StructuredArrow f.right F where + functor := StructuredArrow.preEquivalence.functor F f + inverse := StructuredArrow.preEquivalence.inverse F f + unitIso := NatIso.ofComponents (fun _ => isoMk (isoMk (Iso.refl _))) + counitIso := NatIso.ofComponents (fun _ => isoMk (Iso.refl _)) + +/-- The functor establishing the equivalence `CostructuredArrow.preEquivalence`. -/ +@[simps!] +def CostructuredArrow.preEquivalence.functor (f : CostructuredArrow G e) : + CostructuredArrow (pre F G e) f ⥤ CostructuredArrow F f.left where + obj g := mk g.hom.left + map φ := homMk φ.left.left <| by + have := w φ + simp only [Functor.const_obj_obj] at this ⊢ + rw [← this, comp_left] + simp + +/-- The inverse functor establishing the equivalence `CostructuredArrow.preEquivalence`. -/ +@[simps!] +def CostructuredArrow.preEquivalence.inverse (f : CostructuredArrow G e) : + CostructuredArrow F f.left ⥤ CostructuredArrow (pre F G e) f where + obj g := mk (Y := mk (Y := g.left) (G.map g.hom ≫ f.hom)) (homMk g.hom) + map φ := homMk <| homMk φ.left <| by + simp only [Functor.const_obj_obj, Functor.comp_obj, mk_left, Functor.comp_map, mk_hom_eq_self, + ← w φ, Functor.map_comp, Category.assoc] + +/-- A costructured arrow category on a `CostructuredArrow.pre F G e` functor is equivalent to the +costructured arrow category on F -/ +def CostructuredArrow.preEquivalence (f : CostructuredArrow G e) : + CostructuredArrow (pre F G e) f ≌ CostructuredArrow F f.left where + functor := CostructuredArrow.preEquivalence.functor F f + inverse := CostructuredArrow.preEquivalence.inverse F f + unitIso := NatIso.ofComponents (fun _ => isoMk (isoMk (Iso.refl _))) + counitIso := NatIso.ofComponents (fun _ => isoMk (Iso.refl _)) + +end Pre + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index 96c97533ba899..35224de3361f4 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -813,4 +813,28 @@ theorem IsCofiltered.of_initial (F : C ⥤ D) [Initial F] [IsCofiltered C] : IsC end Filtered +section + +variable {C : Type u₁} [Category.{v₁} C] +variable {D : Type u₂} [Category.{v₂} D] +variable {E : Type u₃} [Category.{v₃} E] + +open Functor + +/-- The functor `StructuredArrow.pre X T S` is final if `T` is final. -/ +instance StructuredArrow.final_pre (T : C ⥤ D) [Final T] (S : D ⥤ E) (X : E) : + Final (pre X T S) := by + refine ⟨fun f => ?_⟩ + rw [isConnected_iff_of_equivalence (StructuredArrow.preEquivalence T f)] + exact Final.out f.right + +/-- The functor `CostructuredArrow.pre X T S` is initial if `T` is initial. -/ +instance CostructuredArrow.initial_pre (T : C ⥤ D) [Initial T] (S : D ⥤ E) (X : E) : + Initial (CostructuredArrow.pre T S X) := by + refine ⟨fun f => ?_⟩ + rw [isConnected_iff_of_equivalence (CostructuredArrow.preEquivalence T f)] + exact Initial.out f.left + +end + end CategoryTheory From d0789f1848d8411ef2875c335fc646c0c054714e Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Sat, 21 Sep 2024 12:24:58 +0000 Subject: [PATCH 074/170] doc(ArchimedeanDensely): fix a typo (#16969) --- Mathlib/GroupTheory/ArchimedeanDensely.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/GroupTheory/ArchimedeanDensely.lean b/Mathlib/GroupTheory/ArchimedeanDensely.lean index 7058cf4ed386d..8b00a52cd33de 100644 --- a/Mathlib/GroupTheory/ArchimedeanDensely.lean +++ b/Mathlib/GroupTheory/ArchimedeanDensely.lean @@ -10,7 +10,7 @@ import Mathlib.Algebra.Order.Group.TypeTags import Mathlib.Algebra.Order.Hom.Monoid /-! -# Archimedean groups are either discrete or densely ordere +# Archimedean groups are either discrete or densely ordered This file proves a few additional facts about linearly ordered additive groups which satisfy the `Archimedean` property -- From 94533cc5157f412ae19173d8566e1ba7146f3ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Kjos-Hanssen?= Date: Sat, 21 Sep 2024 12:33:47 +0000 Subject: [PATCH 075/170] feat: There are only countably many computable functions (#16935) Adding a brief proof that there are countably many computable functions to @digama0 's file. This is a key basic result in computability theory. Co-authored-by: Mario Carneiro --- Mathlib/Computability/PartrecCode.lean | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index 83c17cd86fb12..f563f6babf2c4 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -1015,4 +1015,15 @@ theorem fixed_point₂ {f : Code → ℕ →. ℕ} (hf : Partrec₂ f) : ∃ c : end +/-- There are only countably many partial recursive partial functions `ℕ →. ℕ`. -/ +instance : Countable {f : ℕ →. ℕ // _root_.Partrec f} := by + apply Function.Surjective.countable (f := fun c => ⟨eval c, eval_part.comp (.const c) .id⟩) + intro ⟨f, hf⟩; simpa using exists_code.1 hf + +/-- There are only countably many computable functions `ℕ → ℕ`. -/ +instance : Countable {f : ℕ → ℕ // Computable f} := + @Function.Injective.countable {f : ℕ → ℕ // Computable f} {f : ℕ →. ℕ // _root_.Partrec f} _ + (fun f => ⟨f.val, f.2⟩) + (fun _ _ h => Subtype.val_inj.1 (PFun.lift_injective (by simpa using h))) + end Nat.Partrec.Code From ddb07e50f8b0fbb243752da2d50246da2e8a6fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Sat, 21 Sep 2024 12:33:48 +0000 Subject: [PATCH 076/170] feat(Order/ConditionallyCompleteLattice/Basic): `not_mem_of_lt_csInf'` (#16988) --- Mathlib/Order/ConditionallyCompleteLattice/Basic.lean | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index 2121859395567..9f80770bcdc85 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -1212,6 +1212,9 @@ theorem exists_lt_of_lt_ciSup' {f : ι → α} {a : α} (h : a < ⨆ i, f i) : contrapose! h exact ciSup_le' h +theorem not_mem_of_lt_csInf' {x : α} {s : Set α} (h : x < sInf s) : x ∉ s := + not_mem_of_lt_csInf h (OrderBot.bddBelow s) + theorem ciSup_mono' {ι'} {f : ι → α} {g : ι' → α} (hg : BddAbove (range g)) (h : ∀ i, ∃ i', f i ≤ g i') : iSup f ≤ iSup g := ciSup_le' fun i => Exists.elim (h i) (le_ciSup_of_le hg) From 831db37825f191f25bccb2603532b4b29e931a57 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Sat, 21 Sep 2024 17:09:53 +0000 Subject: [PATCH 077/170] chore: reorganize RingEquiv declarations (#16908) The API for the various `*Equiv` types is inconsistent both in what results are exposed and how they are organized. Previously, in #16867, we started improving the latter, by organizing results into sections for `Mul/AddEquiv` and `AlgEquiv`, and putting the same results in the same order within those. This PR updates RingEquiv to follow the same structure. --- Mathlib/Algebra/Group/Equiv/Basic.lean | 4 + Mathlib/Algebra/Ring/Equiv.lean | 166 +++++++++++++++---------- 2 files changed, 102 insertions(+), 68 deletions(-) diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index 3dace44c49bb8..242b93f9ace47 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -436,6 +436,8 @@ theorem self_trans_symm (e : M ≃* N) : e.trans e.symm = refl M := end trans +section unique + /-- The `MulEquiv` between two monoids with a unique element. -/ @[to_additive "The `AddEquiv` between two `AddMonoid`s with a unique element."] def mulEquivOfUnique {M N} [Unique M] [Unique N] [Mul M] [Mul N] : M ≃* N := @@ -448,6 +450,8 @@ instance {M N} [Unique M] [Unique N] [Mul M] [Mul N] : Unique (M ≃* N) where default := mulEquivOfUnique uniq _ := ext fun _ => Subsingleton.elim _ _ +end unique + end Mul /-! diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index 246dcd9e49330..1f0c32faab5ea 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -126,6 +126,8 @@ section Basic variable [Mul R] [Mul S] [Add R] [Add S] [Mul S'] [Add S'] +section coe + instance : EquivLike (R ≃+* S) R S where coe f := f.toFun inv f := f.invFun @@ -141,30 +143,18 @@ instance : RingEquivClass (R ≃+* S) R S where map_add f := f.map_add' map_mul f := f.map_mul' -@[simp] -theorem toEquiv_eq_coe (f : R ≃+* S) : f.toEquiv = f := - rfl - --- Porting note: `toFun_eq_coe` no longer needed in Lean4 - -@[simp] -theorem coe_toEquiv (f : R ≃+* S) : ⇑(f : R ≃ S) = f := - rfl - -/-- A ring isomorphism preserves multiplication. -/ -protected theorem map_mul (e : R ≃+* S) (x y : R) : e (x * y) = e x * e y := - map_mul e x y - -/-- A ring isomorphism preserves addition. -/ -protected theorem map_add (e : R ≃+* S) (x y : R) : e (x + y) = e x + e y := - map_add e x y - /-- Two ring isomorphisms agree if they are defined by the same underlying function. -/ @[ext] theorem ext {f g : R ≃+* S} (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h +protected theorem congr_arg {f : R ≃+* S} {x x' : R} : x = x' → f x = f x' := + DFunLike.congr_arg f + +protected theorem congr_fun {f g : R ≃+* S} (h : f = g) (x : R) : f x = g x := + DFunLike.congr_fun h x + @[simp] theorem coe_mk (e h₃ h₄) : ⇑(⟨e, h₃, h₄⟩ : R ≃+* S) = e := rfl @@ -175,11 +165,13 @@ theorem coe_mk (e h₃ h₄) : ⇑(⟨e, h₃, h₄⟩ : R ≃+* S) = e := theorem mk_coe (e : R ≃+* S) (e' h₁ h₂ h₃ h₄) : (⟨⟨e, e', h₁, h₂⟩, h₃, h₄⟩ : R ≃+* S) = e := ext fun _ => rfl -protected theorem congr_arg {f : R ≃+* S} {x x' : R} : x = x' → f x = f x' := - DFunLike.congr_arg f +@[simp] +theorem toEquiv_eq_coe (f : R ≃+* S) : f.toEquiv = f := + rfl -protected theorem congr_fun {f g : R ≃+* S} (h : f = g) (x : R) : f x = g x := - DFunLike.congr_fun h x +@[simp] +theorem coe_toEquiv (f : R ≃+* S) : ⇑(f : R ≃ S) = f := + rfl @[simp] theorem toAddEquiv_eq_coe (f : R ≃+* S) : f.toAddEquiv = ↑f := @@ -197,22 +189,45 @@ theorem coe_toMulEquiv (f : R ≃+* S) : ⇑(f : R ≃* S) = f := theorem coe_toAddEquiv (f : R ≃+* S) : ⇑(f : R ≃+ S) = f := rfl -/-- The `RingEquiv` between two semirings with a unique element. -/ -def ringEquivOfUnique {M N} [Unique M] [Unique N] [Add M] [Mul M] [Add N] [Mul N] : M ≃+* N := - { AddEquiv.addEquivOfUnique, MulEquiv.mulEquivOfUnique with } +end coe -instance {M N} [Unique M] [Unique N] [Add M] [Mul M] [Add N] [Mul N] : - Unique (M ≃+* N) where - default := ringEquivOfUnique - uniq _ := ext fun _ => Subsingleton.elim _ _ +section map + +/-- A ring isomorphism preserves multiplication. -/ +protected theorem map_mul (e : R ≃+* S) (x y : R) : e (x * y) = e x * e y := + map_mul e x y + +/-- A ring isomorphism preserves addition. -/ +protected theorem map_add (e : R ≃+* S) (x y : R) : e (x + y) = e x + e y := + map_add e x y + +end map + +section bijective + +protected theorem bijective (e : R ≃+* S) : Function.Bijective e := + EquivLike.bijective e + +protected theorem injective (e : R ≃+* S) : Function.Injective e := + EquivLike.injective e + +protected theorem surjective (e : R ≃+* S) : Function.Surjective e := + EquivLike.surjective e + +end bijective variable (R) +section refl + /-- The identity map is a ring isomorphism. -/ @[refl] def refl : R ≃+* R := { MulEquiv.refl R, AddEquiv.refl R with } +instance : Inhabited (R ≃+* R) := + ⟨RingEquiv.refl R⟩ + @[simp] theorem refl_apply (x : R) : RingEquiv.refl R x = x := rfl @@ -225,22 +240,17 @@ theorem coe_addEquiv_refl : (RingEquiv.refl R : R ≃+ R) = AddEquiv.refl R := theorem coe_mulEquiv_refl : (RingEquiv.refl R : R ≃* R) = MulEquiv.refl R := rfl -instance : Inhabited (R ≃+* R) := - ⟨RingEquiv.refl R⟩ +end refl variable {R} +section symm + /-- The inverse of a ring isomorphism is a ring isomorphism. -/ @[symm] protected def symm (e : R ≃+* S) : S ≃+* R := { e.toMulEquiv.symm, e.toAddEquiv.symm with } -/-- See Note [custom simps projection] -/ -def Simps.symm_apply (e : R ≃+* S) : S → R := - e.symm - -initialize_simps_projections RingEquiv (toFun → apply, invFun → symm_apply) - @[simp] theorem invFun_eq_symm (f : R ≃+* S) : EquivLike.inv f = f.symm := rfl @@ -248,14 +258,6 @@ theorem invFun_eq_symm (f : R ≃+* S) : EquivLike.inv f = f.symm := @[simp] theorem symm_symm (e : R ≃+* S) : e.symm.symm = e := rfl -@[simp] -theorem symm_refl : (RingEquiv.refl R).symm = RingEquiv.refl R := - rfl - -@[simp] -theorem coe_toEquiv_symm (e : R ≃+* S) : (e.symm : S ≃ R) = (e : R ≃ S).symm := - rfl - theorem symm_bijective : Function.Bijective (RingEquiv.symm : (R ≃+* S) → S ≃+* R) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -275,35 +277,14 @@ theorem symm_mk (f : R → S) (g h₁ h₂ h₃ h₄) : invFun := f } := rfl -/-- Transitivity of `RingEquiv`. -/ -@[trans] -protected def trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : R ≃+* S' := - { e₁.toMulEquiv.trans e₂.toMulEquiv, e₁.toAddEquiv.trans e₂.toAddEquiv with } - -theorem trans_apply (e₁ : R ≃+* S) (e₂ : S ≃+* S') (a : R) : e₁.trans e₂ a = e₂ (e₁ a) := - rfl - @[simp] -theorem coe_trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : (e₁.trans e₂ : R → S') = e₂ ∘ e₁ := +theorem symm_refl : (RingEquiv.refl R).symm = RingEquiv.refl R := rfl @[simp] -theorem symm_trans_apply (e₁ : R ≃+* S) (e₂ : S ≃+* S') (a : S') : - (e₁.trans e₂).symm a = e₁.symm (e₂.symm a) := - rfl - -theorem symm_trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : (e₁.trans e₂).symm = e₂.symm.trans e₁.symm := +theorem coe_toEquiv_symm (e : R ≃+* S) : (e.symm : S ≃ R) = (e : R ≃ S).symm := rfl -protected theorem bijective (e : R ≃+* S) : Function.Bijective e := - EquivLike.bijective e - -protected theorem injective (e : R ≃+* S) : Function.Injective e := - EquivLike.injective e - -protected theorem surjective (e : R ≃+* S) : Function.Surjective e := - EquivLike.surjective e - @[simp] theorem apply_symm_apply (e : R ≃+* S) : ∀ x, e (e.symm x) = x := e.toEquiv.apply_symm_apply @@ -315,6 +296,40 @@ theorem symm_apply_apply (e : R ≃+* S) : ∀ x, e.symm (e x) = x := theorem image_eq_preimage (e : R ≃+* S) (s : Set R) : e '' s = e.symm ⁻¹' s := e.toEquiv.image_eq_preimage s +end symm + +section simps + +/-- See Note [custom simps projection] -/ +def Simps.symm_apply (e : R ≃+* S) : S → R := + e.symm + +initialize_simps_projections RingEquiv (toFun → apply, invFun → symm_apply) + +end simps + +section trans + +/-- Transitivity of `RingEquiv`. -/ +@[trans] +protected def trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : R ≃+* S' := + { e₁.toMulEquiv.trans e₂.toMulEquiv, e₁.toAddEquiv.trans e₂.toAddEquiv with } + +@[simp] +theorem coe_trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : (e₁.trans e₂ : R → S') = e₂ ∘ e₁ := + rfl + +theorem trans_apply (e₁ : R ≃+* S) (e₂ : S ≃+* S') (a : R) : e₁.trans e₂ a = e₂ (e₁ a) := + rfl + +@[simp] +theorem symm_trans_apply (e₁ : R ≃+* S) (e₂ : S ≃+* S') (a : S') : + (e₁.trans e₂).symm a = e₁.symm (e₂.symm a) := + rfl + +theorem symm_trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : (e₁.trans e₂).symm = e₂.symm.trans e₁.symm := + rfl + @[simp] theorem coe_mulEquiv_trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : (e₁.trans e₂ : R ≃* S') = (e₁ : R ≃* S).trans ↑e₂ := @@ -325,6 +340,21 @@ theorem coe_addEquiv_trans (e₁ : R ≃+* S) (e₂ : S ≃+* S') : (e₁.trans e₂ : R ≃+ S') = (e₁ : R ≃+ S).trans ↑e₂ := rfl +end trans + +section unique + +/-- The `RingEquiv` between two semirings with a unique element. -/ +def ringEquivOfUnique {M N} [Unique M] [Unique N] [Add M] [Mul M] [Add N] [Mul N] : M ≃+* N := + { AddEquiv.addEquivOfUnique, MulEquiv.mulEquivOfUnique with } + +instance {M N} [Unique M] [Unique N] [Add M] [Mul M] [Add N] [Mul N] : + Unique (M ≃+* N) where + default := ringEquivOfUnique + uniq _ := ext fun _ => Subsingleton.elim _ _ + +end unique + end Basic section Opposite From ba3db161926d69d9d7b6629b38a98630a32204bb Mon Sep 17 00:00:00 2001 From: leanprover-community-bot-assistant Date: Sun, 22 Sep 2024 00:14:25 +0000 Subject: [PATCH 078/170] chore(scripts): update nolints.json (#17010) I am happy to remove some nolints for you! --- scripts/nolints.json | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/nolints.json b/scripts/nolints.json index 197243db4c7e0..c85078ae6db23 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -8,7 +8,6 @@ ["docBlame", "ContT"], ["docBlame", "IsDecEq"], ["docBlame", "IsDecRefl"], - ["docBlame", "IsIdempotent"], ["docBlame", "IsLeftCancel"], ["docBlame", "IsRightCancel"], ["docBlame", "LawfulMonadCont"], @@ -49,7 +48,6 @@ ["docBlame", "«term∫_In_.._,_∂_»"], ["docBlame", "«term∮_InC(_,_),_»"], ["docBlame", "«term⨍_In_.._,_»"], - ["docBlame", "timeCmd"], ["docBlame", "when"], ["docBlame", "whenM"], ["docBlame", "Action.V"], @@ -270,7 +268,6 @@ ["docBlame", "Nat.subInduction"], ["docBlame", "Nat.«termOrd_compl[_]_»"], ["docBlame", "Nat.«termOrd_proj[_]_»"], - ["docBlame", "Nat.twoStepInduction"], ["docBlame", "One.one"], ["docBlame", "OptionT.callCC"], ["docBlame", "OptionT.mkLabel"], @@ -296,9 +293,7 @@ ["docBlame", "ProbabilityTheory.«term_=ₐₛ_»"], ["docBlame", "ProbabilityTheory.«term_[_]»"], ["docBlame", "ProbabilityTheory.«term_×ₖ_»"], - ["docBlame", "ProbabilityTheory.«term_∘ₖ_»"], ["docBlame", "ProbabilityTheory.«term_≤ₐₛ_»"], - ["docBlame", "ProbabilityTheory.«term_⊗ₖ_»"], ["docBlame", "ProbabilityTheory.«term_⟦_|_⟧»"], ["docBlame", "ProbabilityTheory.termℙ"], ["docBlame", "ProbabilityTheory.«term∂_/∂_»"], @@ -579,7 +574,6 @@ ["docBlame", "SlimCheck.Testable.run"], ["docBlame", "SlimCheck.Testable.runProp"], ["docBlame", "Stream'.WSeq.«term_~ʷ_»"], - ["docBlame", "String.toAsciiByteArray.loop"], ["docBlame", "Submodule.quotientPi_aux.invFun"], ["docBlame", "Submodule.quotientPi_aux.toFun"], ["docBlame", "Tactic.Elementwise.tacticElementwise!___"], @@ -637,7 +631,6 @@ ["docBlame", "CategoryTheory.Triangulated.Octahedron.m₃"], ["docBlame", "FirstOrder.Language.ElementaryEmbedding.toFun"], ["docBlame", "FirstOrder.Language.ElementarySubstructure.toSubstructure"], - ["docBlame", "FirstOrder.Language.IsOrdered.leSymb"], ["docBlame", "FirstOrder.Language.LEquiv.invLHom"], ["docBlame", "FirstOrder.Language.LEquiv.toLHom"], ["docBlame", "FirstOrder.Language.LHom.onFunction"], @@ -762,4 +755,4 @@ ["docBlame", "Mathlib.Meta.NormNum.evalAdd.core.ratArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.ratArm"], - ["unusedArguments", "Combinator.K"]] + ["unusedArguments", "Combinator.K"]] \ No newline at end of file From da16ebca64eec75dfaf14a96cbba424963d1cfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 22 Sep 2024 15:36:18 +0000 Subject: [PATCH 079/170] =?UTF-8?q?feat(Finset):=20`(a=20=E2=80=A2=20s).de?= =?UTF-8?q?ns=20=3D=20s.dens`=20(#17020)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From LeanAPAP --- Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index ee19aeb2a8450..14f36bdd515fc 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Algebra.Ring.Pointwise.Set +import Mathlib.Data.Finset.Density import Mathlib.Data.Finset.NAry import Mathlib.Data.Set.Pointwise.Finite import Mathlib.Data.Set.Pointwise.ListOfFn @@ -1697,6 +1698,9 @@ theorem smul_univ [Fintype β] {s : Finset α} (hs : s.Nonempty) : s • (univ : theorem card_smul_finset (a : α) (s : Finset β) : (a • s).card = s.card := card_image_of_injective _ <| MulAction.injective _ +@[to_additive (attr := simp)] +lemma dens_smul_finset [Fintype β] (a : α) (s : Finset β) : (a • s).dens = s.dens := by simp [dens] + /-- If the left cosets of `t` by elements of `s` are disjoint (but not necessarily distinct!), then the size of `t` divides the size of `s • t`. -/ @[to_additive "If the left cosets of `t` by elements of `s` are disjoint (but not necessarily From ed1a8a0388eaba24956bf1eac9a29ac36e5f314a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 22 Sep 2024 18:19:50 +0000 Subject: [PATCH 080/170] feat: `Fintype.prod_ite_mem` (#17017) This specializes the existing `Finset.prod_ite_mem`. From LeanAPAP --- Mathlib/Algebra/BigOperators/Group/Finset.lean | 4 ++++ Mathlib/Algebra/Module/BigOperators.lean | 2 +- Mathlib/Combinatorics/SetFamily/FourFunctions.lean | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index d4e712285b4a5..c418a20c2dc75 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -2008,6 +2008,10 @@ lemma prod_ite_eq_ite_exists (p : ι → Prop) [DecidablePred p] (h : ∀ i j, p variable [DecidableEq ι] +@[to_additive] +lemma prod_ite_mem (s : Finset ι) (f : ι → α) : ∏ i, (if i ∈ s then f i else 1) = ∏ i ∈ s, f i := by + simp + /-- See also `Finset.prod_dite_eq`. -/ @[to_additive "See also `Finset.sum_dite_eq`."] lemma prod_dite_eq (i : ι) (f : ∀ j, i = j → α) : ∏ j, (if h : i = j then f j h else 1) = f i rfl := by diff --git a/Mathlib/Algebra/Module/BigOperators.lean b/Mathlib/Algebra/Module/BigOperators.lean index 6c34557954a88..8b68d57357fd4 100644 --- a/Mathlib/Algebra/Module/BigOperators.lean +++ b/Mathlib/Algebra/Module/BigOperators.lean @@ -54,6 +54,6 @@ lemma sum_piFinset_apply (f : κ → α) (s : Finset κ) (i : ι) : classical rw [Finset.sum_comp] simp only [eval_image_piFinset_const, card_filter_piFinset_const s, ite_smul, zero_smul, smul_sum, - sum_ite_mem, inter_self] + Finset.sum_ite_mem, inter_self] end Fintype diff --git a/Mathlib/Combinatorics/SetFamily/FourFunctions.lean b/Mathlib/Combinatorics/SetFamily/FourFunctions.lean index 2c7b78ec4d1b5..d3bd37943cd19 100644 --- a/Mathlib/Combinatorics/SetFamily/FourFunctions.lean +++ b/Mathlib/Combinatorics/SetFamily/FourFunctions.lean @@ -219,7 +219,7 @@ lemma sum_collapse (h𝒜 : 𝒜 ⊆ (insert a u).powerset) (hu : a ∉ u) : _ = ∑ s ∈ u.powerset ∩ 𝒜, f s + ∑ s ∈ u.powerset.image (insert a) ∩ 𝒜, f s := ?_ _ = ∑ s ∈ u.powerset ∩ 𝒜, f s + ∑ s ∈ ((insert a u).powerset \ u.powerset) ∩ 𝒜, f s := ?_ _ = ∑ s ∈ 𝒜, f s := ?_ - · rw [← sum_ite_mem, ← sum_ite_mem, sum_image, ← sum_add_distrib] + · rw [← Finset.sum_ite_mem, ← Finset.sum_ite_mem, sum_image, ← sum_add_distrib] · exact sum_congr rfl fun s hs ↦ collapse_eq (not_mem_mono (mem_powerset.1 hs) hu) _ _ · exact (insert_erase_invOn.2.injOn).mono fun s hs ↦ not_mem_mono (mem_powerset.1 hs) hu · congr with s From 78c142c32fdfcefbc1aae13e602b5b1bcb103c9c Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 23 Sep 2024 00:11:10 +0000 Subject: [PATCH 081/170] feat(Algebra/Group/Equiv/TypeTags): moving `Multiplicative` inside pi types (#17040) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add equivalences to move `Multiplicative` and `Additive` into the codomain of a pi type, both dependent and non-dependent. ```lean Multiplicative (∀ i : ι, K i) ≃* (∀ i : ι, Multiplicative (K i)) Multiplicative (ι → G) ≃* (ι → Multiplicative G) Additive (∀ i : ι, K i) ≃+ (∀ i : ι, Additive (K i)) Additive (ι → G) ≃+ (ι → Additive G) ``` Also add corresponding `Prod` equivalences. From AperiodicMonotilesLean. --- Mathlib/Algebra/Group/Equiv/TypeTags.lean | 57 ++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Group/Equiv/TypeTags.lean b/Mathlib/Algebra/Group/Equiv/TypeTags.lean index 812c4308708bd..78c085f074666 100644 --- a/Mathlib/Algebra/Group/Equiv/TypeTags.lean +++ b/Mathlib/Algebra/Group/Equiv/TypeTags.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Callum Sutton, Yury Kudryashov -/ import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.TypeTags /-! @@ -11,7 +12,7 @@ import Mathlib.Algebra.Group.TypeTags -/ -variable {G H : Type*} +variable {ι G H : Type*} /-- Reinterpret `G ≃+ H` as `Multiplicative G ≃* Multiplicative H`. -/ @[simps] @@ -113,6 +114,38 @@ and multiplicative endomorphisms of `Multiplicative A`. -/ { AddMonoidHom.toMultiplicative with map_mul' := fun _ _ => rfl } +/-- `Multiplicative (∀ i : ι, K i)` is equivalent to `∀ i : ι, Multiplicative (K i)`. -/ +@[simps] +def MulEquiv.piMultiplicative (K : ι → Type*) [∀ i, Add (K i)] : + Multiplicative (∀ i : ι, K i) ≃* (∀ i : ι, Multiplicative (K i)) where + toFun x := fun i ↦ Multiplicative.ofAdd <| Multiplicative.toAdd x i + invFun x := Multiplicative.ofAdd fun i ↦ Multiplicative.toAdd (x i) + left_inv _ := rfl + right_inv _ := rfl + map_mul' _ _ := rfl + +variable (ι) (G) in +/-- `Multiplicative (ι → G)` is equivalent to `ι → Multiplicative G`. -/ +abbrev MulEquiv.funMultiplicative [Add G] : + Multiplicative (ι → G) ≃* (ι → Multiplicative G) := + MulEquiv.piMultiplicative fun _ ↦ G + +/-- `Additive (∀ i : ι, K i)` is equivalent to `∀ i : ι, Additive (K i)`. -/ +@[simps] +def AddEquiv.piAdditive (K : ι → Type*) [∀ i, Mul (K i)] : + Additive (∀ i : ι, K i) ≃+ (∀ i : ι, Additive (K i)) where + toFun x := fun i ↦ Additive.ofMul <| Additive.toMul x i + invFun x := Additive.ofMul fun i ↦ Additive.toMul (x i) + left_inv _ := rfl + right_inv _ := rfl + map_add' _ _ := rfl + +variable (ι) (G) in +/-- `Additive (ι → G)` is equivalent to `ι → Additive G`. -/ +abbrev AddEquiv.funAdditive [Mul G] : + Additive (ι → G) ≃+ (ι → Additive G) := + AddEquiv.piAdditive fun _ ↦ G + section variable (G) (H) @@ -127,4 +160,26 @@ def AddEquiv.additiveMultiplicative [AddZeroClass G] : Additive (Multiplicative def MulEquiv.multiplicativeAdditive [MulOneClass H] : Multiplicative (Additive H) ≃* H := AddEquiv.toMultiplicative'' (AddEquiv.refl (Additive H)) +/-- `Multiplicative (G × H)` is equivalent to `Multiplicative G × Multiplicative H`. -/ +@[simps] +def MulEquiv.prodMultiplicative [Add G] [Add H] : + Multiplicative (G × H) ≃* Multiplicative G × Multiplicative H where + toFun x := (Multiplicative.ofAdd (Multiplicative.toAdd x).1, + Multiplicative.ofAdd (Multiplicative.toAdd x).2) + invFun := fun (x, y) ↦ Multiplicative.ofAdd (Multiplicative.toAdd x, Multiplicative.toAdd y) + left_inv _ := rfl + right_inv _ := rfl + map_mul' _ _ := rfl + +/-- `Additive (G × H)` is equivalent to `Additive G × Additive H`. -/ +@[simps] +def AddEquiv.prodAdditive [Mul G] [Mul H] : + Additive (G × H) ≃+ Additive G × Additive H where + toFun x := (Additive.ofMul (Additive.toMul x).1, + Additive.ofMul (Additive.toMul x).2) + invFun := fun (x, y) ↦ Additive.ofMul (Additive.toMul x, Additive.toMul y) + left_inv _ := rfl + right_inv _ := rfl + map_add' _ _ := rfl + end From 9890065b5f32e2ab14314294d1b497d229d7c865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 23 Sep 2024 03:11:12 +0000 Subject: [PATCH 082/170] feat(Counterexamples/GameMultiplication): pre-game product cannot be lifted to games (#15764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We show the existence of pre-games `x₁, x₂, y` with `x₁ ≈ x₂` but `x₁ * y ≉ x₂ * y`. --- Counterexamples.lean | 1 + Counterexamples/GameMultiplication.lean | 81 +++++++++++++++++++++++++ Mathlib/SetTheory/Game/PGame.lean | 19 +++--- 3 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 Counterexamples/GameMultiplication.lean diff --git a/Counterexamples.lean b/Counterexamples.lean index 3cc04e2e7faa1..85f441c3cd5d5 100644 --- a/Counterexamples.lean +++ b/Counterexamples.lean @@ -3,6 +3,7 @@ import Counterexamples.CharPZeroNeCharZero import Counterexamples.CliffordAlgebraNotInjective import Counterexamples.Cyclotomic105 import Counterexamples.DirectSumIsInternal +import Counterexamples.GameMultiplication import Counterexamples.Girard import Counterexamples.HomogeneousPrimeNotPrime import Counterexamples.LinearOrderWithPosMulPosEqZero diff --git a/Counterexamples/GameMultiplication.lean b/Counterexamples/GameMultiplication.lean new file mode 100644 index 0000000000000..f28687f92e547 --- /dev/null +++ b/Counterexamples/GameMultiplication.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2024 Violeta Hernández Palacios. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Violeta Hernández Palacios +-/ + +import Mathlib.SetTheory.Game.Basic +import Mathlib.Tactic.FinCases + +/-! +# Multiplication of pre-games can't be lifted to the quotient + +We show that there exist equivalent pregames `x₁ ≈ x₂` and `y` such that `x₁ * y ≉ x₂ * y`. In +particular, we cannot define the multiplication of games in general. + +The specific counterexample we use is `x₁ = y = {0 | 0}` and `x₂ = {-1, 0 | 0, 1}`. The first game +is colloquially known as `star`, so we use the name `star'` for the second. We prove that +`star ≈ star'` and `star * star ≈ star`, but `star' * star ≉ star`. +-/ + +namespace Counterexample + +namespace PGame + +open SetTheory PGame + +/-- The game `{-1, 0 | 0, 1}`, which is equivalent but not identical to `*`. -/ +def star' : PGame := ofLists [0, -1] [0, 1] + +/-- `*'` is its own negative. -/ +theorem neg_star' : -star' = star' := by + simp [star'] + +/-- `*'` is equivalent to `*`. -/ +theorem star'_equiv_star : star' ≈ star := by + have le : star' ≤ star := by + apply PGame.le_of_forall_lf + · rintro ⟨i⟩ + fin_cases i + · exact zero_lf_star + · exact (neg_lt_zero_iff.2 PGame.zero_lt_one).trans_lf zero_lf_star + · exact fun _ => lf_zero_le.2 ⟨⟨0, Nat.zero_lt_two⟩, le_rfl⟩ + constructor + case' right => rw [← neg_le_neg_iff, neg_star, neg_star'] + assumption' + +/-- The equation `** = *` is an identity, though not a relabelling. -/ +theorem star_sq : star * star ≈ star := by + have le : star * star ≤ star := by + rw [le_iff_forall_lf] + constructor <;> + intro i + · apply leftMoves_mul_cases i <;> + intro _ _ + case' hl => rw [mul_moveLeft_inl] + case' hr => rw [mul_moveLeft_inr] + all_goals rw [lf_iff_game_lf]; simpa using zero_lf_star + · refine lf_zero.2 ⟨toRightMovesMul (Sum.inl default), ?_⟩ + rintro (j | j) <;> -- Instance can't be inferred otherwise. + exact isEmptyElim j + constructor + case' right => + rw [← neg_le_neg_iff]; + apply (negMulRelabelling _ _).symm.equiv.1.trans; + rw [neg_star] + assumption' + +/-- `*'* ⧏ *` implies `*'* ≉ *`.-/ +theorem star'_mul_star_lf : star' * star ⧏ star := by + rw [lf_iff_exists_le] + refine Or.inr ⟨toRightMovesMul (Sum.inr ⟨⟨1, Nat.one_lt_two⟩, default⟩), ?_⟩ + rw [mul_moveRight_inr, le_iff_game_le] + simp [star'] + +/-- Pre-game multiplication cannot be lifted to games. -/ +theorem mul_not_lift : ∃ x₁ x₂ y : PGame, x₁ ≈ x₂ ∧ ¬ x₁ * y ≈ x₂ * y := + ⟨_, _, _, ⟨star'_equiv_star, fun h ↦ (PGame.Equiv.trans h star_sq).ge.not_gf star'_mul_star_lf⟩⟩ + +end PGame + +end Counterexample diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index dcdd16d4a47f8..7307ca95f4c59 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -1733,15 +1733,18 @@ instance uniqueStarLeftMoves : Unique star.LeftMoves := instance uniqueStarRightMoves : Unique star.RightMoves := PUnit.unique +theorem zero_lf_star : 0 ⧏ star := by + rw [zero_lf] + use default + rintro ⟨⟩ + +theorem star_lf_zero : star ⧏ 0 := by + rw [lf_zero] + use default + rintro ⟨⟩ + theorem star_fuzzy_zero : star ‖ 0 := - ⟨by - rw [lf_zero] - use default - rintro ⟨⟩, - by - rw [zero_lf] - use default - rintro ⟨⟩⟩ + ⟨star_lf_zero, zero_lf_star⟩ @[simp] theorem neg_star : -star = star := by simp [star] From 6fd58d5c798b0c1754df37d5eb213c1ce5326b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 23 Sep 2024 08:41:16 +0000 Subject: [PATCH 083/170] doc(Algebra/AlgebraicCard): update docstring (#17031) --- Mathlib/Algebra/AlgebraicCard.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/AlgebraicCard.lean b/Mathlib/Algebra/AlgebraicCard.lean index 85eee288ffe90..f8be8db361367 100644 --- a/Mathlib/Algebra/AlgebraicCard.lean +++ b/Mathlib/Algebra/AlgebraicCard.lean @@ -10,10 +10,10 @@ import Mathlib.RingTheory.Algebraic ### Cardinality of algebraic numbers In this file, we prove variants of the following result: the cardinality of algebraic numbers under -an R-algebra is at most `# R[X] * ℵ₀`. +an R-algebra is at most `#R[X] * ℵ₀`. Although this can be used to prove that real or complex transcendental numbers exist, a more direct -proof is given by `Liouville.is_transcendental`. +proof is given by `Liouville.transcendental`. -/ From 5d4874c52a87c499a50f8065f2a71e9caa7866f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 23 Sep 2024 08:50:49 +0000 Subject: [PATCH 084/170] refactor: Make `Finset.sum_le_sum_of_subset_of_nonneg` be gcongr (#17022) From LeanAPAP --- Mathlib/Algebra/Order/BigOperators/Group/Finset.lean | 2 +- Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean | 4 +--- Mathlib/Analysis/SpecialFunctions/Bernstein.lean | 8 ++------ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean index 1d59c749630b2..2f1547de189c6 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean @@ -121,7 +121,7 @@ theorem one_le_prod'' (h : ∀ i : ι, 1 ≤ f i) : 1 ≤ ∏ i ∈ s, f i := theorem prod_le_one' (h : ∀ i ∈ s, f i ≤ 1) : ∏ i ∈ s, f i ≤ 1 := (prod_le_prod' h).trans_eq (by rw [prod_const_one]) -@[to_additive sum_le_sum_of_subset_of_nonneg] +@[to_additive (attr := gcongr) sum_le_sum_of_subset_of_nonneg] theorem prod_le_prod_of_subset_of_one_le' (h : s ⊆ t) (hf : ∀ i ∈ t, i ∉ s → 1 ≤ f i) : ∏ i ∈ s, f i ≤ ∏ i ∈ t, f i := by classical calc diff --git a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean index 200ac13ef97fb..72724bc1976ef 100644 --- a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean @@ -107,11 +107,9 @@ theorem Asymptotics.IsLittleO.sum_range {α : Type*} [NormedAddCommGroup α] {f (add_le_add le_rfl (norm_sum_le_of_le _ fun i hi => hN _ (mem_Ico.1 hi).1)) _ ≤ ‖∑ i ∈ range N, f i‖ + ∑ i ∈ range n, ε / 2 * g i := by gcongr - apply sum_le_sum_of_subset_of_nonneg + · exact fun i _ _ ↦ mul_nonneg (half_pos εpos).le (hg i) · rw [range_eq_Ico] exact Ico_subset_Ico (zero_le _) le_rfl - · intro i _ _ - exact mul_nonneg (half_pos εpos).le (hg i) _ ≤ ε / 2 * ‖∑ i ∈ range n, g i‖ + ε / 2 * ∑ i ∈ range n, g i := by rw [← mul_sum]; gcongr _ = ε * ‖∑ i ∈ range n, g i‖ := by simp only [B] diff --git a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean index 4dbd5bf885328..0c75f3319bb3d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean +++ b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean @@ -252,9 +252,7 @@ theorem bernsteinApproximation_uniform (f : C(I, ℝ)) : _ = ε / 2 * ∑ k ∈ S, bernstein n k x := by rw [Finset.mul_sum] -- In this step we increase the sum over `S` back to a sum over all of `Fin (n+1)`, -- so that we can use `bernstein.probability`. - _ ≤ ε / 2 * ∑ k : Fin (n + 1), bernstein n k x := by - gcongr - exact Finset.sum_le_univ_sum_of_nonneg fun k => bernstein_nonneg + _ ≤ ε / 2 * ∑ k : Fin (n + 1), bernstein n k x := by gcongr; exact S.subset_univ _ = ε / 2 := by rw [bernstein.probability, mul_one] · -- We now turn to working on `Sᶜ`: we control the difference term just using `‖f‖`, -- and then insert a `δ^(-2) * (x - k/n)^2` factor @@ -271,9 +269,7 @@ theorem bernsteinApproximation_uniform (f : C(I, ℝ)) : exact le_of_mem_S_compl m -- Again enlarging the sum from `Sᶜ` to all of `Fin (n+1)` _ ≤ 2 * ‖f‖ * ∑ k : Fin (n + 1), δ ^ (-2 : ℤ) * ((x : ℝ) - k/ₙ) ^ 2 * bernstein n k x := by - gcongr - refine Finset.sum_le_univ_sum_of_nonneg fun k => ?_ - positivity + gcongr; exact Sᶜ.subset_univ _ = 2 * ‖f‖ * δ ^ (-2 : ℤ) * ∑ k : Fin (n + 1), ((x : ℝ) - k/ₙ) ^ 2 * bernstein n k x := by conv_rhs => rw [mul_assoc, Finset.mul_sum] From b4dda71e1bd8297df387af10ff0ca7f0a5127385 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Mon, 23 Sep 2024 08:50:51 +0000 Subject: [PATCH 085/170] chore(*): Use non-greek variable names here and there (#17035) ... for monoids, rings, and fields. --- .../Algebra/Associated/OrderedCommMonoid.lean | 8 +-- Mathlib/Algebra/Field/Basic.lean | 70 +++++++++---------- Mathlib/Algebra/Field/Defs.lean | 50 ++++++------- 3 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Mathlib/Algebra/Associated/OrderedCommMonoid.lean b/Mathlib/Algebra/Associated/OrderedCommMonoid.lean index 16c1b23b72bf2..ab1745e4359de 100644 --- a/Mathlib/Algebra/Associated/OrderedCommMonoid.lean +++ b/Mathlib/Algebra/Associated/OrderedCommMonoid.lean @@ -23,14 +23,14 @@ Then we show that the quotient type `Associates` is a monoid and prove basic properties of this quotient. -/ -variable {α : Type*} [CancelCommMonoidWithZero α] +variable {M : Type*} [CancelCommMonoidWithZero M] namespace Associates -instance instOrderedCommMonoid : OrderedCommMonoid (Associates α) where - mul_le_mul_left := fun a _ ⟨d, hd⟩ c => hd.symm ▸ mul_assoc c a d ▸ le_mul_right (α := α) +instance instOrderedCommMonoid : OrderedCommMonoid (Associates M) where + mul_le_mul_left := fun a _ ⟨d, hd⟩ c => hd.symm ▸ mul_assoc c a d ▸ le_mul_right -instance : CanonicallyOrderedCommMonoid (Associates α) where +instance : CanonicallyOrderedCommMonoid (Associates M) where exists_mul_of_le h := h le_self_mul _ b := ⟨b, rfl⟩ bot_le _ := one_le diff --git a/Mathlib/Algebra/Field/Basic.lean b/Mathlib/Algebra/Field/Basic.lean index fa1a788fb74a7..570a5278b9b56 100644 --- a/Mathlib/Algebra/Field/Basic.lean +++ b/Mathlib/Algebra/Field/Basic.lean @@ -18,16 +18,16 @@ open Function OrderDual Set universe u -variable {α β K : Type*} +variable {K L : Type*} section DivisionSemiring -variable [DivisionSemiring α] {a b c d : α} +variable [DivisionSemiring K] {a b c d : K} -theorem add_div (a b c : α) : (a + b) / c = a / c + b / c := by simp_rw [div_eq_mul_inv, add_mul] +theorem add_div (a b c : K) : (a + b) / c = a / c + b / c := by simp_rw [div_eq_mul_inv, add_mul] @[field_simps] -theorem div_add_div_same (a b c : α) : a / c + b / c = (a + b) / c := +theorem div_add_div_same (a b c : K) : a / c + b / c = (a + b) / c := (add_div _ _ _).symm theorem same_add_div (h : b ≠ 0) : (b + a) / b = 1 + a / b := by rw [← div_self h, add_div] @@ -49,15 +49,15 @@ theorem one_div_mul_add_mul_one_div_eq_one_div_add_one_div (ha : a ≠ 0) (hb : 1 / a * (a + b) * (1 / b) = 1 / a + 1 / b := by simpa only [one_div] using (inv_add_inv' ha hb).symm -theorem add_div_eq_mul_add_div (a b : α) (hc : c ≠ 0) : a + b / c = (a * c + b) / c := +theorem add_div_eq_mul_add_div (a b : K) (hc : c ≠ 0) : a + b / c = (a * c + b) / c := (eq_div_iff_mul_eq hc).2 <| by rw [right_distrib, div_mul_cancel₀ _ hc] @[field_simps] -theorem add_div' (a b c : α) (hc : c ≠ 0) : b + a / c = (b * c + a) / c := by +theorem add_div' (a b c : K) (hc : c ≠ 0) : b + a / c = (b * c + a) / c := by rw [add_div, mul_div_cancel_right₀ _ hc] @[field_simps] -theorem div_add' (a b c : α) (hc : c ≠ 0) : a / c + b = (a + b * c) / c := by +theorem div_add' (a b c : K) (hc : c ≠ 0) : a / c + b = (a + b * c) / c := by rwa [add_comm, add_div', add_comm] protected theorem Commute.div_add_div (hbc : Commute b c) (hbd : Commute b d) (hb : b ≠ 0) @@ -167,9 +167,9 @@ end DivisionRing section Semifield -variable [Semifield α] {a b c d : α} +variable [Semifield K] {a b c d : K} -theorem div_add_div (a : α) (c : α) (hb : b ≠ 0) (hd : d ≠ 0) : +theorem div_add_div (a : K) (c : K) (hb : b ≠ 0) (hd : d ≠ 0) : a / b + c / d = (a * d + b * c) / (b * d) := (Commute.all b _).div_add_div (Commute.all _ _) hb hd @@ -211,7 +211,7 @@ end Field namespace RingHom -protected theorem injective [DivisionRing α] [Semiring β] [Nontrivial β] (f : α →+* β) : +protected theorem injective [DivisionRing K] [Semiring L] [Nontrivial L] (f : K →+* L) : Injective f := (injective_iff_map_eq_zero f).2 fun _ ↦ (map_eq_zero f).1 @@ -242,18 +242,18 @@ noncomputable abbrev Field.ofIsUnitOrEqZero [CommRing R] (h : ∀ a : R, IsUnit end NoncomputableDefs namespace Function.Injective -variable [Zero α] [Add α] [Neg α] [Sub α] [One α] [Mul α] [Inv α] [Div α] [SMul ℕ α] [SMul ℤ α] - [SMul ℚ≥0 α] [SMul ℚ α] [Pow α ℕ] [Pow α ℤ] [NatCast α] [IntCast α] [NNRatCast α] [RatCast α] - (f : α → β) (hf : Injective f) +variable [Zero K] [Add K] [Neg K] [Sub K] [One K] [Mul K] [Inv K] [Div K] [SMul ℕ K] [SMul ℤ K] + [SMul ℚ≥0 K] [SMul ℚ K] [Pow K ℕ] [Pow K ℤ] [NatCast K] [IntCast K] [NNRatCast K] [RatCast K] + (f : K → L) (hf : Injective f) /-- Pullback a `DivisionSemiring` along an injective function. -/ -- See note [reducible non-instances] -protected abbrev divisionSemiring [DivisionSemiring β] (zero : f 0 = 0) (one : f 1 = 1) +protected abbrev divisionSemiring [DivisionSemiring L] (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y) (mul : ∀ x y, f (x * y) = f x * f y) (inv : ∀ x, f x⁻¹ = (f x)⁻¹) (div : ∀ x y, f (x / y) = f x / f y) (nsmul : ∀ (n : ℕ) (x), f (n • x) = n • f x) (nnqsmul : ∀ (q : ℚ≥0) (x), f (q • x) = q • f x) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) - (natCast : ∀ n : ℕ, f n = n) (nnratCast : ∀ q : ℚ≥0, f q = q) : DivisionSemiring α where + (natCast : ∀ n : ℕ, f n = n) (nnratCast : ∀ q : ℚ≥0, f q = q) : DivisionSemiring K where toSemiring := hf.semiring f zero one add mul nsmul npow natCast __ := hf.groupWithZero f zero one mul inv div npow zpow nnratCast_def q := hf <| by rw [nnratCast, NNRat.cast_def, div, natCast, natCast] @@ -262,7 +262,7 @@ protected abbrev divisionSemiring [DivisionSemiring β] (zero : f 0 = 0) (one : /-- Pullback a `DivisionSemiring` along an injective function. -/ -- See note [reducible non-instances] -protected abbrev divisionRing [DivisionRing β] (zero : f 0 = 0) (one : f 1 = 1) +protected abbrev divisionRing [DivisionRing L] (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y) (mul : ∀ x y, f (x * y) = f x * f y) (neg : ∀ x, f (-x) = -f x) (sub : ∀ x y, f (x - y) = f x - f y) (inv : ∀ x, f x⁻¹ = (f x)⁻¹) (div : ∀ x y, f (x / y) = f x / f y) @@ -270,7 +270,7 @@ protected abbrev divisionRing [DivisionRing β] (zero : f 0 = 0) (one : f 1 = 1) (nnqsmul : ∀ (q : ℚ≥0) (x), f (q • x) = q • f x) (qsmul : ∀ (q : ℚ) (x), f (q • x) = q • f x) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) (natCast : ∀ n : ℕ, f n = n) (intCast : ∀ n : ℤ, f n = n) (nnratCast : ∀ q : ℚ≥0, f q = q) - (ratCast : ∀ q : ℚ, f q = q) : DivisionRing α where + (ratCast : ∀ q : ℚ, f q = q) : DivisionRing K where toRing := hf.ring f zero one add mul neg sub nsmul zsmul npow natCast intCast __ := hf.groupWithZero f zero one mul inv div npow zpow __ := hf.divisionSemiring f zero one add mul inv div nsmul nnqsmul npow zpow natCast nnratCast @@ -280,19 +280,19 @@ protected abbrev divisionRing [DivisionRing β] (zero : f 0 = 0) (one : f 1 = 1) /-- Pullback a `Field` along an injective function. -/ -- See note [reducible non-instances] -protected abbrev semifield [Semifield β] (zero : f 0 = 0) (one : f 1 = 1) +protected abbrev semifield [Semifield L] (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y) (mul : ∀ x y, f (x * y) = f x * f y) (inv : ∀ x, f x⁻¹ = (f x)⁻¹) (div : ∀ x y, f (x / y) = f x / f y) (nsmul : ∀ (n : ℕ) (x), f (n • x) = n • f x) (nnqsmul : ∀ (q : ℚ≥0) (x), f (q • x) = q • f x) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) - (natCast : ∀ n : ℕ, f n = n) (nnratCast : ∀ q : ℚ≥0, f q = q) : Semifield α where + (natCast : ∀ n : ℕ, f n = n) (nnratCast : ∀ q : ℚ≥0, f q = q) : Semifield K where toCommSemiring := hf.commSemiring f zero one add mul nsmul npow natCast __ := hf.commGroupWithZero f zero one mul inv div npow zpow __ := hf.divisionSemiring f zero one add mul inv div nsmul nnqsmul npow zpow natCast nnratCast /-- Pullback a `Field` along an injective function. -/ -- See note [reducible non-instances] -protected abbrev field [Field β] (zero : f 0 = 0) (one : f 1 = 1) +protected abbrev field [Field L] (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y) (mul : ∀ x y, f (x * y) = f x * f y) (neg : ∀ x, f (-x) = -f x) (sub : ∀ x y, f (x - y) = f x - f y) (inv : ∀ x, f x⁻¹ = (f x)⁻¹) (div : ∀ x y, f (x / y) = f x / f y) @@ -301,7 +301,7 @@ protected abbrev field [Field β] (zero : f 0 = 0) (one : f 1 = 1) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) (natCast : ∀ n : ℕ, f n = n) (intCast : ∀ n : ℤ, f n = n) (nnratCast : ∀ q : ℚ≥0, f q = q) (ratCast : ∀ q : ℚ, f q = q) : - Field α where + Field K where toCommRing := hf.commRing f zero one add mul neg sub nsmul zsmul npow natCast intCast __ := hf.divisionRing f zero one add mul neg sub inv div nsmul zsmul nnqsmul qsmul npow zpow natCast intCast nnratCast ratCast @@ -312,30 +312,30 @@ end Function.Injective namespace OrderDual -instance instRatCast [RatCast α] : RatCast αᵒᵈ := ‹_› -instance instDivisionSemiring [DivisionSemiring α] : DivisionSemiring αᵒᵈ := ‹_› -instance instDivisionRing [DivisionRing α] : DivisionRing αᵒᵈ := ‹_› -instance instSemifield [Semifield α] : Semifield αᵒᵈ := ‹_› -instance instField [Field α] : Field αᵒᵈ := ‹_› +instance instRatCast [RatCast K] : RatCast Kᵒᵈ := ‹_› +instance instDivisionSemiring [DivisionSemiring K] : DivisionSemiring Kᵒᵈ := ‹_› +instance instDivisionRing [DivisionRing K] : DivisionRing Kᵒᵈ := ‹_› +instance instSemifield [Semifield K] : Semifield Kᵒᵈ := ‹_› +instance instField [Field K] : Field Kᵒᵈ := ‹_› end OrderDual -@[simp] lemma toDual_ratCast [RatCast α] (n : ℚ) : toDual (n : α) = n := rfl +@[simp] lemma toDual_ratCast [RatCast K] (n : ℚ) : toDual (n : K) = n := rfl -@[simp] lemma ofDual_ratCast [RatCast α] (n : ℚ) : (ofDual n : α) = n := rfl +@[simp] lemma ofDual_ratCast [RatCast K] (n : ℚ) : (ofDual n : K) = n := rfl /-! ### Lexicographic order -/ namespace Lex -instance instRatCast [RatCast α] : RatCast (Lex α) := ‹_› -instance instDivisionSemiring [DivisionSemiring α] : DivisionSemiring (Lex α) := ‹_› -instance instDivisionRing [DivisionRing α] : DivisionRing (Lex α) := ‹_› -instance instSemifield [Semifield α] : Semifield (Lex α) := ‹_› -instance instField [Field α] : Field (Lex α) := ‹_› +instance instRatCast [RatCast K] : RatCast (Lex K) := ‹_› +instance instDivisionSemiring [DivisionSemiring K] : DivisionSemiring (Lex K) := ‹_› +instance instDivisionRing [DivisionRing K] : DivisionRing (Lex K) := ‹_› +instance instSemifield [Semifield K] : Semifield (Lex K) := ‹_› +instance instField [Field K] : Field (Lex K) := ‹_› end Lex -@[simp] lemma toLex_ratCast [RatCast α] (n : ℚ) : toLex (n : α) = n := rfl +@[simp] lemma toLex_ratCast [RatCast K] (n : ℚ) : toLex (n : K) = n := rfl -@[simp] lemma ofLex_ratCast [RatCast α] (n : ℚ) : (ofLex n : α) = n := rfl +@[simp] lemma ofLex_ratCast [RatCast K] (n : ℚ) : (ofLex n : K) = n := rfl diff --git a/Mathlib/Algebra/Field/Defs.lean b/Mathlib/Algebra/Field/Defs.lean index 4943b798adf4c..834f25d5fc450 100644 --- a/Mathlib/Algebra/Field/Defs.lean +++ b/Mathlib/Algebra/Field/Defs.lean @@ -54,7 +54,7 @@ open Function Set universe u -variable {α β K : Type*} +variable {K : Type*} /-- The default definition of the coercion `ℚ≥0 → K` for a division semiring `K`. @@ -81,23 +81,23 @@ itself). See also note [forgetful inheritance]. If the division semiring has positive characteristic `p`, our division by zero convention forces `nnratCast (1 / p) = 1 / 0 = 0`. -/ -class DivisionSemiring (α : Type*) extends Semiring α, GroupWithZero α, NNRatCast α where +class DivisionSemiring (K : Type*) extends Semiring K, GroupWithZero K, NNRatCast K where protected nnratCast := NNRat.castRec /-- However `NNRat.cast` is defined, it must be propositionally equal to `a / b`. Do not use this lemma directly. Use `NNRat.cast_def` instead. -/ - protected nnratCast_def (q : ℚ≥0) : (NNRat.cast q : α) = q.num / q.den := by intros; rfl + protected nnratCast_def (q : ℚ≥0) : (NNRat.cast q : K) = q.num / q.den := by intros; rfl /-- Scalar multiplication by a nonnegative rational number. Unless there is a risk of a `Module ℚ≥0 _` instance diamond, write `nnqsmul := _`. This will set `nnqsmul` to `(NNRat.cast · * ·)` thanks to unification in the default proof of `nnqsmul_def`. Do not use directly. Instead use the `•` notation. -/ - protected nnqsmul : ℚ≥0 → α → α + protected nnqsmul : ℚ≥0 → K → K /-- However `qsmul` is defined, it must be propositionally equal to multiplication by `Rat.cast`. Do not use this lemma directly. Use `NNRat.smul_def` instead. -/ - protected nnqsmul_def (q : ℚ≥0) (a : α) : nnqsmul q a = NNRat.cast q * a := by intros; rfl + protected nnqsmul_def (q : ℚ≥0) (a : K) : nnqsmul q a = NNRat.cast q * a := by intros; rfl /-- A `DivisionRing` is a `Ring` with multiplicative inverses for nonzero elements. @@ -109,48 +109,48 @@ See also note [forgetful inheritance]. Similarly, there are maps `nnratCast ℚ If the division ring has positive characteristic `p`, our division by zero convention forces `ratCast (1 / p) = 1 / 0 = 0`. -/ -class DivisionRing (α : Type*) - extends Ring α, DivInvMonoid α, Nontrivial α, NNRatCast α, RatCast α where +class DivisionRing (K : Type*) + extends Ring K, DivInvMonoid K, Nontrivial K, NNRatCast K, RatCast K where /-- For a nonzero `a`, `a⁻¹` is a right multiplicative inverse. -/ - protected mul_inv_cancel : ∀ (a : α), a ≠ 0 → a * a⁻¹ = 1 + protected mul_inv_cancel : ∀ (a : K), a ≠ 0 → a * a⁻¹ = 1 /-- The inverse of `0` is `0` by convention. -/ - protected inv_zero : (0 : α)⁻¹ = 0 + protected inv_zero : (0 : K)⁻¹ = 0 protected nnratCast := NNRat.castRec /-- However `NNRat.cast` is defined, it must be equal to `a / b`. Do not use this lemma directly. Use `NNRat.cast_def` instead. -/ - protected nnratCast_def (q : ℚ≥0) : (NNRat.cast q : α) = q.num / q.den := by intros; rfl + protected nnratCast_def (q : ℚ≥0) : (NNRat.cast q : K) = q.num / q.den := by intros; rfl /-- Scalar multiplication by a nonnegative rational number. Unless there is a risk of a `Module ℚ≥0 _` instance diamond, write `nnqsmul := _`. This will set `nnqsmul` to `(NNRat.cast · * ·)` thanks to unification in the default proof of `nnqsmul_def`. Do not use directly. Instead use the `•` notation. -/ - protected nnqsmul : ℚ≥0 → α → α + protected nnqsmul : ℚ≥0 → K → K /-- However `qsmul` is defined, it must be propositionally equal to multiplication by `Rat.cast`. Do not use this lemma directly. Use `NNRat.smul_def` instead. -/ - protected nnqsmul_def (q : ℚ≥0) (a : α) : nnqsmul q a = NNRat.cast q * a := by intros; rfl + protected nnqsmul_def (q : ℚ≥0) (a : K) : nnqsmul q a = NNRat.cast q * a := by intros; rfl protected ratCast := Rat.castRec /-- However `Rat.cast q` is defined, it must be propositionally equal to `q.num / q.den`. Do not use this lemma directly. Use `Rat.cast_def` instead. -/ - protected ratCast_def (q : ℚ) : (Rat.cast q : α) = q.num / q.den := by intros; rfl + protected ratCast_def (q : ℚ) : (Rat.cast q : K) = q.num / q.den := by intros; rfl /-- Scalar multiplication by a rational number. Unless there is a risk of a `Module ℚ _` instance diamond, write `qsmul := _`. This will set `qsmul` to `(Rat.cast · * ·)` thanks to unification in the default proof of `qsmul_def`. Do not use directly. Instead use the `•` notation. -/ - protected qsmul : ℚ → α → α + protected qsmul : ℚ → K → K /-- However `qsmul` is defined, it must be propositionally equal to multiplication by `Rat.cast`. Do not use this lemma directly. Use `Rat.cast_def` instead. -/ - protected qsmul_def (a : ℚ) (x : α) : qsmul a x = Rat.cast a * x := by intros; rfl + protected qsmul_def (a : ℚ) (x : K) : qsmul a x = Rat.cast a * x := by intros; rfl -- see Note [lower instance priority] -instance (priority := 100) DivisionRing.toDivisionSemiring [DivisionRing α] : DivisionSemiring α := - { ‹DivisionRing α› with } +instance (priority := 100) DivisionRing.toDivisionSemiring [DivisionRing K] : DivisionSemiring K := + { ‹DivisionRing K› with } /-- A `Semifield` is a `CommSemiring` with multiplicative inverses for nonzero elements. @@ -161,7 +161,7 @@ itself). See also note [forgetful inheritance]. If the semifield has positive characteristic `p`, our division by zero convention forces `nnratCast (1 / p) = 1 / 0 = 0`. -/ -class Semifield (α : Type*) extends CommSemiring α, DivisionSemiring α, CommGroupWithZero α +class Semifield (K : Type*) extends CommSemiring K, DivisionSemiring K, CommGroupWithZero K /-- A `Field` is a `CommRing` with multiplicative inverses for nonzero elements. @@ -175,19 +175,19 @@ If the field has positive characteristic `p`, our division by zero convention fo class Field (K : Type u) extends CommRing K, DivisionRing K -- see Note [lower instance priority] -instance (priority := 100) Field.toSemifield [Field α] : Semifield α := { ‹Field α› with } +instance (priority := 100) Field.toSemifield [Field K] : Semifield K := { ‹Field K› with } namespace NNRat -variable [DivisionSemiring α] +variable [DivisionSemiring K] -instance (priority := 100) smulDivisionSemiring : SMul ℚ≥0 α := ⟨DivisionSemiring.nnqsmul⟩ +instance (priority := 100) smulDivisionSemiring : SMul ℚ≥0 K := ⟨DivisionSemiring.nnqsmul⟩ -lemma cast_def (q : ℚ≥0) : (q : α) = q.num / q.den := DivisionSemiring.nnratCast_def _ -lemma smul_def (q : ℚ≥0) (a : α) : q • a = q * a := DivisionSemiring.nnqsmul_def q a +lemma cast_def (q : ℚ≥0) : (q : K) = q.num / q.den := DivisionSemiring.nnratCast_def _ +lemma smul_def (q : ℚ≥0) (a : K) : q • a = q * a := DivisionSemiring.nnqsmul_def q a -variable (α) +variable (K) -@[simp] lemma smul_one_eq_cast (q : ℚ≥0) : q • (1 : α) = q := by rw [NNRat.smul_def, mul_one] +@[simp] lemma smul_one_eq_cast (q : ℚ≥0) : q • (1 : K) = q := by rw [NNRat.smul_def, mul_one] @[deprecated (since := "2024-05-03")] alias smul_one_eq_coe := smul_one_eq_cast From 09c50fb84c0b5e89b270ff20af6ae7e4bd61511e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 23 Sep 2024 09:33:46 +0000 Subject: [PATCH 086/170] =?UTF-8?q?feat:=20`a=20*=20a=E2=81=BB=C2=B9=20?= =?UTF-8?q?=E2=89=A4=201`=20(#17023)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From LeanAPAP --- Mathlib/Algebra/Order/Field/Defs.lean | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Mathlib/Algebra/Order/Field/Defs.lean b/Mathlib/Algebra/Order/Field/Defs.lean index 5e36efa7b7f81..ad7ae9d36bb7a 100644 --- a/Mathlib/Algebra/Order/Field/Defs.lean +++ b/Mathlib/Algebra/Order/Field/Defs.lean @@ -35,3 +35,43 @@ class LinearOrderedField (α : Type*) extends LinearOrderedCommRing α, Field α instance (priority := 100) LinearOrderedField.toLinearOrderedSemifield [LinearOrderedField α] : LinearOrderedSemifield α := { LinearOrderedRing.toLinearOrderedSemiring, ‹LinearOrderedField α› with } + +variable [LinearOrderedSemifield α] {a b : α} + +/-- Equality holds when `a ≠ 0`. See `mul_inv_cancel`. -/ +lemma mul_inv_le_one : a * a⁻¹ ≤ 1 := by obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +/-- Equality holds when `a ≠ 0`. See `inv_mul_cancel`. -/ +lemma inv_mul_le_one : a⁻¹ * a ≤ 1 := by obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +/-- Equality holds when `a ≠ 0`. See `mul_inv_cancel_left`. -/ +lemma mul_inv_left_le (hb : 0 ≤ b) : a * (a⁻¹ * b) ≤ b := by + obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +/-- Equality holds when `a ≠ 0`. See `mul_inv_cancel_left`. -/ +lemma le_mul_inv_left (hb : b ≤ 0) : b ≤ a * (a⁻¹ * b) := by + obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +/-- Equality holds when `a ≠ 0`. See `inv_mul_cancel_left`. -/ +lemma inv_mul_left_le (hb : 0 ≤ b) : a⁻¹ * (a * b) ≤ b := by + obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +/-- Equality holds when `a ≠ 0`. See `inv_mul_cancel_left`. -/ +lemma le_inv_mul_left (hb : b ≤ 0) : b ≤ a⁻¹ * (a * b) := by + obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +/-- Equality holds when `b ≠ 0`. See `mul_inv_cancel_right`. -/ +lemma mul_inv_right_le (ha : 0 ≤ a) : a * b * b⁻¹ ≤ a := by + obtain rfl | hb := eq_or_ne b 0 <;> simp [*] + +/-- Equality holds when `b ≠ 0`. See `mul_inv_cancel_right`. -/ +lemma le_mul_inv_right (ha : a ≤ 0) : a ≤ a * b * b⁻¹ := by + obtain rfl | hb := eq_or_ne b 0 <;> simp [*] + +/-- Equality holds when `b ≠ 0`. See `inv_mul_cancel_right`. -/ +lemma inv_mul_right_le (ha : 0 ≤ a) : a * b⁻¹ * b ≤ a := by + obtain rfl | hb := eq_or_ne b 0 <;> simp [*] + +/-- Equality holds when `b ≠ 0`. See `inv_mul_cancel_right`. -/ +lemma le_inv_mul_right (ha : a ≤ 0) : a ≤ a * b⁻¹ * b := by + obtain rfl | hb := eq_or_ne b 0 <;> simp [*] From 20d470bd63093b1e8e772b586abf7509f3dffc80 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Mon, 23 Sep 2024 11:30:09 +0000 Subject: [PATCH 087/170] refactor: switch final use of Batteries.HashMap to Std.HashMap (#17042) Co-authored-by: Parcly Taxel --- Mathlib.lean | 1 + Mathlib/Std/Data/HashMap.lean | 22 +++++++++++++++++++ Mathlib/Tactic/Linarith/Datatypes.lean | 3 +-- Mathlib/Tactic/Linarith/Frontend.lean | 2 +- .../Linarith/Oracle/FourierMotzkin.lean | 7 +++--- .../Linarith/Oracle/SimplexAlgorithm.lean | 7 ++---- Mathlib/Tactic/Linarith/Verification.lean | 4 ++-- 7 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 Mathlib/Std/Data/HashMap.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9aac5382744a8..35810d46201d8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4130,6 +4130,7 @@ import Mathlib.SetTheory.Surreal.Multiplication import Mathlib.SetTheory.ZFC.Basic import Mathlib.SetTheory.ZFC.Ordinal import Mathlib.SetTheory.ZFC.Rank +import Mathlib.Std.Data.HashMap import Mathlib.Tactic import Mathlib.Tactic.Abel import Mathlib.Tactic.AdaptationNote diff --git a/Mathlib/Std/Data/HashMap.lean b/Mathlib/Std/Data/HashMap.lean new file mode 100644 index 0000000000000..19199a7f7e67b --- /dev/null +++ b/Mathlib/Std/Data/HashMap.lean @@ -0,0 +1,22 @@ +/- +Copyright (c) 2024 Lean FRO. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kim Morrison +-/ +import Std.Data.HashMap.Basic + +/-! +# Convenience functions for hash maps + +These will be reimplemented in the Lean standard library. +-/ + +namespace Std.HashMap + +variable {α β γ : Type _} [BEq α] [Hashable α] + +/-- Apply a function to the values of a hash map. -/ +def mapVal (f : α → β → γ) (m : HashMap α β) : HashMap α γ := + m.fold (fun acc k v => acc.insert k (f k v)) HashMap.empty + +end Std.HashMap diff --git a/Mathlib/Tactic/Linarith/Datatypes.lean b/Mathlib/Tactic/Linarith/Datatypes.lean index d34b1f949f653..4b939583e90ec 100644 --- a/Mathlib/Tactic/Linarith/Datatypes.lean +++ b/Mathlib/Tactic/Linarith/Datatypes.lean @@ -6,7 +6,6 @@ Authors: Robert Y. Lewis import Mathlib.Tactic.Linarith.Lemmas import Mathlib.Tactic.Ring.Basic import Mathlib.Util.SynthesizeUsing -import Batteries.Data.HashMap.Basic /-! # Datatypes for `linarith` @@ -312,7 +311,7 @@ structure CertificateOracle : Type where `hyps` by eliminating all variables ≤ `max_var`. If successful, it returns a map `coeff : Nat → Nat` as a certificate. This map represents that we can find a contradiction by taking the sum `∑ (coeff i) * hyps[i]`. -/ - produceCertificate (hyps : List Comp) (max_var : Nat) : MetaM (Batteries.HashMap Nat Nat) + produceCertificate (hyps : List Comp) (max_var : Nat) : MetaM (Std.HashMap Nat Nat) /-! ### Auxiliary functions diff --git a/Mathlib/Tactic/Linarith/Frontend.lean b/Mathlib/Tactic/Linarith/Frontend.lean index 2143364d3f3ea..f23bfb3fa0d6e 100644 --- a/Mathlib/Tactic/Linarith/Frontend.lean +++ b/Mathlib/Tactic/Linarith/Frontend.lean @@ -92,7 +92,7 @@ disequality hypotheses, since this would lead to a number of runs exponential in disequalities in the context. The oracle is very modular. It can easily be replaced with another function of type -`List Comp → ℕ → MetaM ((Batteries.HashMap ℕ ℕ))`, +`List Comp → ℕ → MetaM ((Std.HashMap ℕ ℕ))`, which takes a list of comparisons and the largest variable index appearing in those comparisons, and returns a map from comparison indices to coefficients. An alternate oracle can be specified in the `LinarithConfig` object. diff --git a/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean b/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean index e65a8f3eba4cd..053e563cbbe5e 100644 --- a/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean +++ b/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean @@ -3,8 +3,9 @@ Copyright (c) 2020 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis -/ +import Mathlib.Std.Data.HashMap +import Batteries.Lean.HashMap import Mathlib.Tactic.Linarith.Datatypes -import Batteries.Data.HashMap.WF /-! # The Fourier-Motzkin elimination procedure @@ -61,8 +62,8 @@ For example, suppose `cs` is produced by scaling assumption 2 by 5, and adding to that the sum of assumptions 1 and 2. `cs.flatten` maps `1 ↦ 1, 2 ↦ 6`. -/ -def CompSource.flatten : CompSource → HashMap Nat Nat - | (CompSource.assump n) => HashMap.empty.insert n 1 +def CompSource.flatten : CompSource → Std.HashMap Nat Nat + | (CompSource.assump n) => Std.HashMap.empty.insert n 1 | (CompSource.add c1 c2) => (CompSource.flatten c1).mergeWith (fun _ b b' => b + b') (CompSource.flatten c2) | (CompSource.scale n c) => (CompSource.flatten c).mapVal (fun _ v => v * n) diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm.lean index e582844d49f0a..daeddd75376e8 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm.lean @@ -14,8 +14,6 @@ The algorithm's entry point is the function `Linarith.SimplexAlgorithm.findPosit See the file `PositiveVector.lean` for details of how the procedure works. -/ -open Batteries - namespace Linarith.SimplexAlgorithm /-- Preprocess the goal to pass it to `Linarith.SimplexAlgorithm.findPositiveVector`. -/ @@ -30,11 +28,10 @@ def preprocess (matType : ℕ → ℕ → Type) [UsableInSimplexAlgorithm matTyp /-- Extract the certificate from the `vec` found by `Linarith.SimplexAlgorithm.findPositiveVector`. -/ -def postprocess (vec : Array ℚ) : HashMap ℕ ℕ := +def postprocess (vec : Array ℚ) : Std.HashMap ℕ ℕ := let common_den : ℕ := vec.foldl (fun acc item => acc.lcm item.den) 1 let vecNat : Array ℕ := vec.map (fun x : ℚ => (x * common_den).floor.toNat) - HashMap.ofList <| vecNat.toList.enum.filter (fun ⟨_, item⟩ => item != 0) - + Std.HashMap.empty.insertMany <| vecNat.toList.enum.filter (fun ⟨_, item⟩ => item != 0) end SimplexAlgorithm diff --git a/Mathlib/Tactic/Linarith/Verification.lean b/Mathlib/Tactic/Linarith/Verification.lean index 2439b1d8def02..9cda494376353 100644 --- a/Mathlib/Tactic/Linarith/Verification.lean +++ b/Mathlib/Tactic/Linarith/Verification.lean @@ -202,7 +202,7 @@ def proveFalseByLinarith (transparency : TransparencyMode) (oracle : Certificate trace[linarith.detail] "... finished `linearFormsAndMaxVar`." trace[linarith.detail] "{comps}" -- perform the elimination and fail if no contradiction is found. - let certificate : Batteries.HashMap Nat Nat ← try + let certificate : Std.HashMap Nat Nat ← try oracle.produceCertificate comps max_var catch e => trace[linarith] e.toMessageData @@ -210,7 +210,7 @@ def proveFalseByLinarith (transparency : TransparencyMode) (oracle : Certificate trace[linarith] "linarith has found a contradiction: {certificate.toList}" let enum_inputs := inputs.enum -- construct a list pairing nonzero coeffs with the proof of their corresponding comparison - let zip := enum_inputs.filterMap fun ⟨n, e⟩ => (certificate.find? n).map (e, ·) + let zip := enum_inputs.filterMap fun ⟨n, e⟩ => (certificate[n]?).map (e, ·) let mls ← zip.mapM fun ⟨e, n⟩ => do mulExpr n (← leftOfIneqProof e) -- `sm` is the sum of input terms, scaled to cancel out all variables. let sm ← addExprs mls From ac537a4a8fe7098691db632b0e1f493b8c993b61 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 23 Sep 2024 11:56:11 +0000 Subject: [PATCH 088/170] chore: generalize `IsBoundedBilinearMap` to seminormed spaces (#17011) The claim in `Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean` that > This file contains statements about operator norm for which it really matters that the > underlying space has a norm (rather than just a seminorm). was not entirely true. The main trick is to case on whether the norm of an element is zero, rather than on that element itself being zero. Unfortunately this causes some minor elaboration issues downstream, but they are easy to work around. --- Mathlib/Analysis/Calculus/ContDiff/Basic.lean | 2 +- Mathlib/Analysis/Calculus/FDeriv/Mul.lean | 15 +++--- .../Analysis/InnerProductSpace/Calculus.lean | 9 ++-- .../Normed/Operator/BoundedLinearMaps.lean | 25 +++++---- .../NormedSpace/OperatorNorm/Bilinear.lean | 48 +++++++++++++++++ .../NormedSpace/OperatorNorm/NormedSpace.lean | 52 ------------------- 6 files changed, 79 insertions(+), 72 deletions(-) diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index eecfb2a1688da..f9cc1aee3a4f1 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -802,7 +802,7 @@ theorem ContDiff.clm_comp {g : X → F →L[𝕜] G} {f : X → E →L[𝕜] F} theorem ContDiffOn.clm_comp {g : X → F →L[𝕜] G} {f : X → E →L[𝕜] F} {s : Set X} (hg : ContDiffOn 𝕜 n g s) (hf : ContDiffOn 𝕜 n f s) : ContDiffOn 𝕜 n (fun x => (g x).comp (f x)) s := - isBoundedBilinearMap_comp.contDiff.comp_contDiff_on₂ hg hf + (isBoundedBilinearMap_comp (𝕜 := 𝕜) (E := E) (F := F) (G := G)).contDiff.comp_contDiff_on₂ hg hf theorem ContDiff.clm_apply {f : E → F →L[𝕜] G} {g : E → F} {n : ℕ∞} (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) : ContDiff 𝕜 n fun x => (f x) (g x) := diff --git a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean index 9c79b4bf2279c..47dd475da18fc 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean @@ -50,20 +50,20 @@ variable {H : Type*} [NormedAddCommGroup H] [NormedSpace 𝕜 H] {c : E → G theorem HasStrictFDerivAt.clm_comp (hc : HasStrictFDerivAt c c' x) (hd : HasStrictFDerivAt d d' x) : HasStrictFDerivAt (fun y => (c y).comp (d y)) ((compL 𝕜 F G H (c x)).comp d' + ((compL 𝕜 F G H).flip (d x)).comp c') x := - (isBoundedBilinearMap_comp.hasStrictFDerivAt (c x, d x)).comp x <| hc.prod hd + (isBoundedBilinearMap_comp.hasStrictFDerivAt (c x, d x) :).comp x <| hc.prod hd @[fun_prop] theorem HasFDerivWithinAt.clm_comp (hc : HasFDerivWithinAt c c' s x) (hd : HasFDerivWithinAt d d' s x) : HasFDerivWithinAt (fun y => (c y).comp (d y)) ((compL 𝕜 F G H (c x)).comp d' + ((compL 𝕜 F G H).flip (d x)).comp c') s x := - (isBoundedBilinearMap_comp.hasFDerivAt (c x, d x)).comp_hasFDerivWithinAt x <| hc.prod hd + (isBoundedBilinearMap_comp.hasFDerivAt (c x, d x) :).comp_hasFDerivWithinAt x <| hc.prod hd @[fun_prop] theorem HasFDerivAt.clm_comp (hc : HasFDerivAt c c' x) (hd : HasFDerivAt d d' x) : HasFDerivAt (fun y => (c y).comp (d y)) ((compL 𝕜 F G H (c x)).comp d' + ((compL 𝕜 F G H).flip (d x)).comp c') x := - (isBoundedBilinearMap_comp.hasFDerivAt (c x, d x)).comp x <| hc.prod hd + (isBoundedBilinearMap_comp.hasFDerivAt (c x, d x) :).comp x <| hc.prod hd @[fun_prop] theorem DifferentiableWithinAt.clm_comp (hc : DifferentiableWithinAt 𝕜 c s x) @@ -107,12 +107,12 @@ theorem HasStrictFDerivAt.clm_apply (hc : HasStrictFDerivAt c c' x) theorem HasFDerivWithinAt.clm_apply (hc : HasFDerivWithinAt c c' s x) (hu : HasFDerivWithinAt u u' s x) : HasFDerivWithinAt (fun y => (c y) (u y)) ((c x).comp u' + c'.flip (u x)) s x := - (isBoundedBilinearMap_apply.hasFDerivAt (c x, u x)).comp_hasFDerivWithinAt x (hc.prod hu) + (isBoundedBilinearMap_apply.hasFDerivAt (c x, u x) :).comp_hasFDerivWithinAt x (hc.prod hu) @[fun_prop] theorem HasFDerivAt.clm_apply (hc : HasFDerivAt c c' x) (hu : HasFDerivAt u u' x) : HasFDerivAt (fun y => (c y) (u y)) ((c x).comp u' + c'.flip (u x)) x := - (isBoundedBilinearMap_apply.hasFDerivAt (c x, u x)).comp x (hc.prod hu) + (isBoundedBilinearMap_apply.hasFDerivAt (c x, u x) :).comp x (hc.prod hu) @[fun_prop] theorem DifferentiableWithinAt.clm_apply (hc : DifferentiableWithinAt 𝕜 c s x) @@ -239,12 +239,13 @@ theorem HasStrictFDerivAt.smul (hc : HasStrictFDerivAt c c' x) (hf : HasStrictFD @[fun_prop] theorem HasFDerivWithinAt.smul (hc : HasFDerivWithinAt c c' s x) (hf : HasFDerivWithinAt f f' s x) : HasFDerivWithinAt (fun y => c y • f y) (c x • f' + c'.smulRight (f x)) s x := - (isBoundedBilinearMap_smul.hasFDerivAt (c x, f x)).comp_hasFDerivWithinAt x <| hc.prod hf + (isBoundedBilinearMap_smul.hasFDerivAt (𝕜 := 𝕜) (c x, f x) :).comp_hasFDerivWithinAt x <| + hc.prod hf @[fun_prop] theorem HasFDerivAt.smul (hc : HasFDerivAt c c' x) (hf : HasFDerivAt f f' x) : HasFDerivAt (fun y => c y • f y) (c x • f' + c'.smulRight (f x)) x := - (isBoundedBilinearMap_smul.hasFDerivAt (c x, f x)).comp x <| hc.prod hf + (isBoundedBilinearMap_smul.hasFDerivAt (𝕜 := 𝕜) (c x, f x) :).comp x <| hc.prod hf @[fun_prop] theorem DifferentiableWithinAt.smul (hc : DifferentiableWithinAt 𝕜 c s x) diff --git a/Mathlib/Analysis/InnerProductSpace/Calculus.lean b/Mathlib/Analysis/InnerProductSpace/Calculus.lean index 031592910f445..44808e4d72423 100644 --- a/Mathlib/Analysis/InnerProductSpace/Calculus.lean +++ b/Mathlib/Analysis/InnerProductSpace/Calculus.lean @@ -80,15 +80,18 @@ theorem HasFDerivWithinAt.inner (hf : HasFDerivWithinAt f f' s x) (hg : HasFDerivWithinAt g g' s x) : HasFDerivWithinAt (fun t => ⟪f t, g t⟫) ((fderivInnerCLM 𝕜 (f x, g x)).comp <| f'.prod g') s x := - (isBoundedBilinearMap_inner.hasFDerivAt (f x, g x)).comp_hasFDerivWithinAt x (hf.prod hg) + isBoundedBilinearMap_inner (𝕜 := 𝕜) (E := E) + |>.hasFDerivAt (f x, g x) |>.comp_hasFDerivWithinAt x (hf.prod hg) theorem HasStrictFDerivAt.inner (hf : HasStrictFDerivAt f f' x) (hg : HasStrictFDerivAt g g' x) : HasStrictFDerivAt (fun t => ⟪f t, g t⟫) ((fderivInnerCLM 𝕜 (f x, g x)).comp <| f'.prod g') x := - (isBoundedBilinearMap_inner.hasStrictFDerivAt (f x, g x)).comp x (hf.prod hg) + isBoundedBilinearMap_inner (𝕜 := 𝕜) (E := E) + |>.hasStrictFDerivAt (f x, g x) |>.comp x (hf.prod hg) theorem HasFDerivAt.inner (hf : HasFDerivAt f f' x) (hg : HasFDerivAt g g' x) : HasFDerivAt (fun t => ⟪f t, g t⟫) ((fderivInnerCLM 𝕜 (f x, g x)).comp <| f'.prod g') x := - (isBoundedBilinearMap_inner.hasFDerivAt (f x, g x)).comp x (hf.prod hg) + isBoundedBilinearMap_inner (𝕜 := 𝕜) (E := E) + |>.hasFDerivAt (f x, g x) |>.comp x (hf.prod hg) theorem HasDerivWithinAt.inner {f g : ℝ → E} {f' g' : E} {s : Set ℝ} {x : ℝ} (hf : HasDerivWithinAt f f' s x) (hg : HasDerivWithinAt g g' s x) : diff --git a/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean b/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean index 114bd3205cea4..4d0fea4e147c4 100644 --- a/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean +++ b/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean @@ -59,14 +59,14 @@ open Filter (Tendsto) open Metric ContinuousLinearMap -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} - [NormedAddCommGroup G] [NormedSpace 𝕜 G] +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [SeminormedAddCommGroup E] + [NormedSpace 𝕜 E] {F : Type*} [SeminormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} + [SeminormedAddCommGroup G] [NormedSpace 𝕜 G] /-- A function `f` satisfies `IsBoundedLinearMap 𝕜 f` if it is linear and satisfies the inequality `‖f x‖ ≤ M * ‖x‖` for some positive constant `M`. -/ -structure IsBoundedLinearMap (𝕜 : Type*) [NormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] (f : E → F) extends +structure IsBoundedLinearMap (𝕜 : Type*) [NormedField 𝕜] {E : Type*} [SeminormedAddCommGroup E] + [NormedSpace 𝕜 E] {F : Type*} [SeminormedAddCommGroup F] [NormedSpace 𝕜 F] (f : E → F) extends IsLinearMap 𝕜 f : Prop where bound : ∃ M, 0 < M ∧ ∀ x : E, ‖f x‖ ≤ M * ‖x‖ @@ -186,7 +186,7 @@ variable {ι : Type*} [Fintype ι] /-- Taking the cartesian product of two continuous multilinear maps is a bounded linear operation. -/ -theorem isBoundedLinearMap_prod_multilinear {E : ι → Type*} [∀ i, NormedAddCommGroup (E i)] +theorem isBoundedLinearMap_prod_multilinear {E : ι → Type*} [∀ i, SeminormedAddCommGroup (E i)] [∀ i, NormedSpace 𝕜 (E i)] : IsBoundedLinearMap 𝕜 fun p : ContinuousMultilinearMap 𝕜 E F × ContinuousMultilinearMap 𝕜 E G => p.1.prod p.2 where @@ -244,7 +244,7 @@ variable {R : Type*} variable {𝕜₂ 𝕜' : Type*} [NontriviallyNormedField 𝕜'] [NontriviallyNormedField 𝕜₂] variable {M : Type*} [TopologicalSpace M] variable {σ₁₂ : 𝕜 →+* 𝕜₂} -variable {G' : Type*} [NormedAddCommGroup G'] [NormedSpace 𝕜₂ G'] [NormedSpace 𝕜' G'] +variable {G' : Type*} [SeminormedAddCommGroup G'] [NormedSpace 𝕜₂ G'] [NormedSpace 𝕜' G'] variable [SMulCommClass 𝕜₂ 𝕜' G'] section Semiring @@ -374,7 +374,7 @@ theorem IsBoundedBilinearMap.isBoundedLinearMap_right (h : IsBoundedBilinearMap (h.toContinuousLinearMap x).isBoundedLinearMap theorem isBoundedBilinearMap_smul {𝕜' : Type*} [NormedField 𝕜'] [NormedAlgebra 𝕜 𝕜'] {E : Type*} - [NormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedSpace 𝕜' E] [IsScalarTower 𝕜 𝕜' E] : + [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedSpace 𝕜' E] [IsScalarTower 𝕜 𝕜' E] : IsBoundedBilinearMap 𝕜 fun p : 𝕜' × E => p.1 • p.2 := (lsmul 𝕜 𝕜' : 𝕜' →L[𝕜] E →L[𝕜] E).isBoundedBilinearMap @@ -436,7 +436,7 @@ variable (𝕜) /-- The function `ContinuousLinearMap.mulLeftRight : 𝕜' × 𝕜' → (𝕜' →L[𝕜] 𝕜')` is a bounded bilinear map. -/ -theorem ContinuousLinearMap.mulLeftRight_isBoundedBilinear (𝕜' : Type*) [NormedRing 𝕜'] +theorem ContinuousLinearMap.mulLeftRight_isBoundedBilinear (𝕜' : Type*) [SeminormedRing 𝕜'] [NormedAlgebra 𝕜 𝕜'] : IsBoundedBilinearMap 𝕜 fun p : 𝕜' × 𝕜' => ContinuousLinearMap.mulLeftRight 𝕜 𝕜' p.1 p.2 := (ContinuousLinearMap.mulLeftRight 𝕜 𝕜').isBoundedBilinearMap @@ -471,9 +471,16 @@ theorem ContinuousOn.clm_apply {X} [TopologicalSpace X] {f : X → (E →L[𝕜] ContinuousOn (fun x ↦ f x (g x)) s := isBoundedBilinearMap_apply.continuous.comp_continuousOn (hf.prod hg) +end + namespace ContinuousLinearEquiv +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] +variable {F : Type*} [SeminormedAddCommGroup F] [NormedSpace 𝕜 F] + open Set +open scoped Topology /-! ### The set of continuous linear equivalences between two Banach spaces is open diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean index 1d70cb3750159..61f5199b50531 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean @@ -409,6 +409,54 @@ theorem map_add_add (f : E →L[𝕜] Fₗ →L[𝕜] Gₗ) (x x' : E) (y y' : F simp only [map_add, add_apply, coe_deriv₂, add_assoc] abel +/-- The norm of the tensor product of a scalar linear map and of an element of a normed space +is the product of the norms. -/ +@[simp] +theorem norm_smulRight_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRight c f‖ = ‖c‖ * ‖f‖ := by + refine le_antisymm ?_ ?_ + · refine opNorm_le_bound _ (mul_nonneg (norm_nonneg _) (norm_nonneg _)) fun x => ?_ + calc + ‖c x • f‖ = ‖c x‖ * ‖f‖ := norm_smul _ _ + _ ≤ ‖c‖ * ‖x‖ * ‖f‖ := mul_le_mul_of_nonneg_right (le_opNorm _ _) (norm_nonneg _) + _ = ‖c‖ * ‖f‖ * ‖x‖ := by ring + · obtain hf | hf := (norm_nonneg f).eq_or_gt + · simp [hf] + · rw [← le_div_iff₀ hf] + refine opNorm_le_bound _ (div_nonneg (norm_nonneg _) (norm_nonneg f)) fun x => ?_ + rw [div_mul_eq_mul_div, le_div_iff₀ hf] + calc + ‖c x‖ * ‖f‖ = ‖c x • f‖ := (norm_smul _ _).symm + _ = ‖smulRight c f x‖ := rfl + _ ≤ ‖smulRight c f‖ * ‖x‖ := le_opNorm _ _ + +/-- The non-negative norm of the tensor product of a scalar linear map and of an element of a normed +space is the product of the non-negative norms. -/ +@[simp] +theorem nnnorm_smulRight_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRight c f‖₊ = ‖c‖₊ * ‖f‖₊ := + NNReal.eq <| c.norm_smulRight_apply f + +variable (𝕜 E Fₗ) in +/-- `ContinuousLinearMap.smulRight` as a continuous trilinear map: +`smulRightL (c : E →L[𝕜] 𝕜) (f : F) (x : E) = c x • f`. -/ +def smulRightL : (E →L[𝕜] 𝕜) →L[𝕜] Fₗ →L[𝕜] E →L[𝕜] Fₗ := + LinearMap.mkContinuous₂ + { toFun := smulRightₗ + map_add' := fun c₁ c₂ => by + ext x + simp only [add_smul, coe_smulRightₗ, add_apply, smulRight_apply, LinearMap.add_apply] + map_smul' := fun m c => by + ext x + dsimp + rw [smul_smul] } + 1 fun c x => by + simp only [coe_smulRightₗ, one_mul, norm_smulRight_apply, LinearMap.coe_mk, AddHom.coe_mk, + le_refl] + + +@[simp] +theorem norm_smulRightL_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRightL 𝕜 E Fₗ c f‖ = ‖c‖ * ‖f‖ := + norm_smulRight_apply c f + end ContinuousLinearMap end SemiNormed diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean index d07b5ac33cae4..8530ba797f7ed 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean @@ -200,58 +200,6 @@ theorem opNorm_comp_linearIsometryEquiv (f : F →SL[σ₂₃] G) (g : F' ≃ₛ @[deprecated (since := "2024-02-02")] alias op_norm_comp_linearIsometryEquiv := opNorm_comp_linearIsometryEquiv -/-- The norm of the tensor product of a scalar linear map and of an element of a normed space -is the product of the norms. -/ -@[simp] -theorem norm_smulRight_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRight c f‖ = ‖c‖ * ‖f‖ := by - refine le_antisymm ?_ ?_ - · refine opNorm_le_bound _ (mul_nonneg (norm_nonneg _) (norm_nonneg _)) fun x => ?_ - calc - ‖c x • f‖ = ‖c x‖ * ‖f‖ := norm_smul _ _ - _ ≤ ‖c‖ * ‖x‖ * ‖f‖ := mul_le_mul_of_nonneg_right (le_opNorm _ _) (norm_nonneg _) - _ = ‖c‖ * ‖f‖ * ‖x‖ := by ring - · by_cases h : f = 0 - · simp [h] - · have : 0 < ‖f‖ := norm_pos_iff.2 h - rw [← le_div_iff₀ this] - refine opNorm_le_bound _ (div_nonneg (norm_nonneg _) (norm_nonneg f)) fun x => ?_ - rw [div_mul_eq_mul_div, le_div_iff₀ this] - calc - ‖c x‖ * ‖f‖ = ‖c x • f‖ := (norm_smul _ _).symm - _ = ‖smulRight c f x‖ := rfl - _ ≤ ‖smulRight c f‖ * ‖x‖ := le_opNorm _ _ - -/-- The non-negative norm of the tensor product of a scalar linear map and of an element of a normed -space is the product of the non-negative norms. -/ -@[simp] -theorem nnnorm_smulRight_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRight c f‖₊ = ‖c‖₊ * ‖f‖₊ := - NNReal.eq <| c.norm_smulRight_apply f - -variable (𝕜 E Fₗ) - - -/-- `ContinuousLinearMap.smulRight` as a continuous trilinear map: -`smulRightL (c : E →L[𝕜] 𝕜) (f : F) (x : E) = c x • f`. -/ -def smulRightL : (E →L[𝕜] 𝕜) →L[𝕜] Fₗ →L[𝕜] E →L[𝕜] Fₗ := - LinearMap.mkContinuous₂ - { toFun := smulRightₗ - map_add' := fun c₁ c₂ => by - ext x - simp only [add_smul, coe_smulRightₗ, add_apply, smulRight_apply, LinearMap.add_apply] - map_smul' := fun m c => by - ext x - dsimp - rw [smul_smul] } - 1 fun c x => by - simp only [coe_smulRightₗ, one_mul, norm_smulRight_apply, LinearMap.coe_mk, AddHom.coe_mk, - le_refl] - -variable {𝕜 E Fₗ} - -@[simp] -theorem norm_smulRightL_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRightL 𝕜 E Fₗ c f‖ = ‖c‖ * ‖f‖ := - norm_smulRight_apply c f - @[simp] theorem norm_smulRightL (c : E →L[𝕜] 𝕜) [Nontrivial Fₗ] : ‖smulRightL 𝕜 E Fₗ c‖ = ‖c‖ := ContinuousLinearMap.homothety_norm _ c.norm_smulRight_apply From 9a329fb9ed78734d85679055a2a748ea804ea403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 23 Sep 2024 12:22:53 +0000 Subject: [PATCH 089/170] =?UTF-8?q?feat:=20`=E2=8C=88a=E2=8C=89=20<=202=20?= =?UTF-8?q?*=20a`=20(#17024)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From LeanAPAP --- Mathlib/Algebra/Order/Floor.lean | 94 ++++++++++++++++++++++++++++ Mathlib/Algebra/Order/Ring/Cast.lean | 4 ++ 2 files changed, 98 insertions(+) diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index d909f10092190..7d9f071cca4ea 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -11,6 +11,7 @@ import Mathlib.Data.Nat.Cast.Order.Field import Mathlib.Data.Set.Subsingleton import Mathlib.Order.GaloisConnection import Mathlib.Tactic.Abel +import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.Linarith import Mathlib.Tactic.Positivity @@ -499,6 +500,46 @@ theorem floor_div_eq_div (m n : ℕ) : ⌊(m : α) / n⌋₊ = m / n := by end LinearOrderedSemifield +section LinearOrderedField +variable [LinearOrderedField α] [FloorSemiring α] {a b : α} + +lemma mul_lt_floor (hb₀ : 0 < b) (hb : b < 1) (hba : ⌈b / (1 - b)⌉₊ ≤ a) : b * a < ⌊a⌋₊ := by + calc + b * a < b * (⌊a⌋₊ + 1) := by gcongr; exacts [hb₀, lt_floor_add_one _] + _ ≤ ⌊a⌋₊ := by + rw [_root_.mul_add_one, ← le_sub_iff_add_le', ← one_sub_mul, ← div_le_iff₀' (by linarith), + ← ceil_le] + exact le_floor hba + +lemma ceil_lt_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉₊ / b < a) : ⌈a⌉₊ < b * a := by + obtain hab | hba := le_total a (b - 1)⁻¹ + · calc + ⌈a⌉₊ ≤ (⌈(b - 1)⁻¹⌉₊ : α) := by gcongr + _ < b * a := by rwa [← div_lt_iff']; positivity + · rw [← sub_pos] at hb + calc + ⌈a⌉₊ < a + 1 := ceil_lt_add_one <| hba.trans' <| by positivity + _ = a + (b - 1) * (b - 1)⁻¹ := by rw [mul_inv_cancel₀]; positivity + _ ≤ a + (b - 1) * a := by gcongr; positivity + _ = b * a := by rw [sub_one_mul, add_sub_cancel] + +lemma ceil_le_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉₊ / b ≤ a) : ⌈a⌉₊ ≤ b * a := by + obtain rfl | hba := hba.eq_or_lt + · rw [mul_div_cancel₀, cast_le, ceil_le] + exact _root_.div_le_self (by positivity) hb.le + · positivity + · exact (ceil_lt_mul hb hba).le + +lemma div_two_lt_floor (ha : 1 ≤ a) : a / 2 < ⌊a⌋₊ := by + rw [div_eq_inv_mul]; refine mul_lt_floor ?_ ?_ ?_ <;> norm_num; assumption + +lemma ceil_lt_two_mul (ha : 2⁻¹ < a) : ⌈a⌉₊ < 2 * a := + ceil_lt_mul one_lt_two (by norm_num at ha ⊢; exact ha) + +lemma ceil_le_two_mul (ha : 2⁻¹ ≤ a) : ⌈a⌉₊ ≤ 2 * a := + ceil_le_mul one_lt_two (by norm_num at ha ⊢; exact ha) + +end LinearOrderedField end Nat /-- There exists at most one `FloorSemiring` structure on a linear ordered semiring. -/ @@ -1070,6 +1111,9 @@ theorem ceil_le_floor_add_one (a : α) : ⌈a⌉ ≤ ⌊a⌋ + 1 := by theorem le_ceil (a : α) : a ≤ ⌈a⌉ := gc_ceil_coe.le_u_l a +lemma le_ceil_iff : z ≤ ⌈a⌉ ↔ z - 1 < a := by rw [← sub_one_lt_iff, lt_ceil]; norm_cast +lemma ceil_lt_iff : ⌈a⌉ < z ↔ a ≤ z - 1 := by rw [← le_sub_one_iff, ceil_le]; norm_cast + @[simp] theorem ceil_intCast (z : ℤ) : ⌈(z : α)⌉ = z := eq_of_forall_ge_iff fun a => by rw [ceil_le, Int.cast_le] @@ -1200,6 +1244,56 @@ theorem ceil_sub_self_eq (ha : fract a ≠ 0) : (⌈a⌉ : α) - a = 1 - fract a rw [(or_iff_right ha).mp (fract_eq_zero_or_add_one_sub_ceil a)] abel +section LinearOrderedField +variable {k : Type*} [LinearOrderedField k] [FloorRing k] {a b : k} + +lemma mul_lt_floor (hb₀ : 0 < b) (hb : b < 1) (hba : ⌈b / (1 - b)⌉ ≤ a) : b * a < ⌊a⌋ := by + calc + b * a < b * (⌊a⌋ + 1) := by gcongr; exacts [hb₀, lt_floor_add_one _] + _ ≤ ⌊a⌋ := by + rwa [_root_.mul_add_one, ← le_sub_iff_add_le', ← one_sub_mul, ← div_le_iff₀' (by linarith), + ← ceil_le, le_floor] + +lemma ceil_div_ceil_inv_sub_one (ha : 1 ≤ a) : ⌈⌈(a - 1)⁻¹⌉ / a⌉ = ⌈(a - 1)⁻¹⌉ := by + obtain rfl | ha := ha.eq_or_lt + · simp + have : 0 < a - 1 := by linarith + have : 0 < ⌈(a - 1)⁻¹⌉ := ceil_pos.2 <| by positivity + refine le_antisymm (ceil_le.2 <| div_le_self (by positivity) ha.le) <| ?_ + rw [le_ceil_iff, sub_lt_comm, div_eq_mul_inv, ← mul_one_sub, + ← lt_div_iff (sub_pos.2 <| inv_lt_one ha)] + convert ceil_lt_add_one _ using 1 + field_simp + +lemma ceil_lt_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉ / b < a) : ⌈a⌉ < b * a := by + obtain hab | hba := le_total a (b - 1)⁻¹ + · calc + ⌈a⌉ ≤ (⌈(b - 1)⁻¹⌉ : k) := by gcongr + _ < b * a := by rwa [← div_lt_iff']; positivity + · rw [← sub_pos] at hb + calc + ⌈a⌉ < a + 1 := ceil_lt_add_one _ + _ = a + (b - 1) * (b - 1)⁻¹ := by rw [mul_inv_cancel₀]; positivity + _ ≤ a + (b - 1) * a := by gcongr; positivity + _ = b * a := by rw [sub_one_mul, add_sub_cancel] + +lemma ceil_le_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉ / b ≤ a) : ⌈a⌉ ≤ b * a := by + obtain rfl | hba := hba.eq_or_lt + · rw [ceil_div_ceil_inv_sub_one hb.le, mul_div_cancel₀] + positivity + · exact (ceil_lt_mul hb hba).le + +lemma div_two_lt_floor (ha : 1 ≤ a) : a / 2 < ⌊a⌋ := by + rw [div_eq_inv_mul]; refine mul_lt_floor ?_ ?_ ?_ <;> norm_num; assumption + +lemma ceil_lt_two_mul (ha : 2⁻¹ < a) : ⌈a⌉ < 2 * a := + ceil_lt_mul one_lt_two (by norm_num at ha ⊢; exact ha) + +lemma ceil_le_two_mul (ha : 2⁻¹ ≤ a) : ⌈a⌉ ≤ 2 * a := + ceil_le_mul one_lt_two (by norm_num at ha ⊢; exact ha) + +end LinearOrderedField + /-! #### Intervals -/ @[simp] diff --git a/Mathlib/Algebra/Order/Ring/Cast.lean b/Mathlib/Algebra/Order/Ring/Cast.lean index 98e9a362cfbdd..bd47e1f894415 100644 --- a/Mathlib/Algebra/Order/Ring/Cast.lean +++ b/Mathlib/Algebra/Order/Ring/Cast.lean @@ -37,6 +37,8 @@ lemma cast_mono : Monotone (Int.cast : ℤ → R) := by rw [← sub_nonneg, ← cast_sub, ← hk, cast_natCast] exact k.cast_nonneg' +@[gcongr] protected lemma GCongr.intCast_mono {m n : ℤ} (hmn : m ≤ n) : (m : R) ≤ n := cast_mono hmn + variable [NeZero (1 : R)] {m n : ℤ} @[simp] lemma cast_nonneg : ∀ {n : ℤ}, (0 : R) ≤ n ↔ 0 ≤ n @@ -53,6 +55,8 @@ lemma cast_strictMono : StrictMono (fun x : ℤ => (x : R)) := @[simp, norm_cast] lemma cast_lt : (m : R) < n ↔ m < n := cast_strictMono.lt_iff_lt +@[gcongr] protected alias ⟨_, GCongr.intCast_strictMono⟩ := Int.cast_lt + @[simp] lemma cast_nonpos : (n : R) ≤ 0 ↔ n ≤ 0 := by rw [← cast_zero, cast_le] @[simp] lemma cast_pos : (0 : R) < n ↔ 0 < n := by rw [← cast_zero, cast_lt] From 596cf190f25182265220a3f3cabcbee0417270cc Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:07:24 +0000 Subject: [PATCH 090/170] chore: update Mathlib dependencies 2024-09-23 (#17050) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index 05d82c3f77869..d035304d7779b 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "2ce0037d487217469a1efeb9ea8196fe15ab9c46", + "rev": "35d1cd731ad832c9f1d860c4d8ec1c7c3ab96823", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 3eedc3b5f7c9a486d15fa301a4c1d1cc09a748ef Mon Sep 17 00:00:00 2001 From: Jiang Jiedong Date: Mon, 23 Sep 2024 13:56:35 +0000 Subject: [PATCH 091/170] feat(RingTheory/Valuation): add one lemma `isEquiv_iff_val_lt_val` (#16764) Add a single lemma `Valuation.isEquiv_iff_val_lt_val`. Co-authored-by: Jiang Jiedong <107380768+jjdishere@users.noreply.github.com> --- Mathlib/RingTheory/Valuation/Basic.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index 9d007aff35686..c64c33a0023cf 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -412,6 +412,14 @@ theorem isEquiv_of_map_strictMono [LinearOrderedCommMonoidWithZero Γ₀] (H : StrictMono f) : IsEquiv (v.map f H.monotone) v := fun _x _y => ⟨H.le_iff_le.mp, fun h => H.monotone h⟩ +theorem isEquiv_iff_val_lt_val [LinearOrderedCommGroupWithZero Γ₀] + [LinearOrderedCommGroupWithZero Γ'₀] {v : Valuation K Γ₀} {v' : Valuation K Γ'₀} : + v.IsEquiv v' ↔ ∀ {x y : K}, v x < v y ↔ v' x < v' y := by + simp only [IsEquiv, le_iff_le_iff_lt_iff_lt] + exact forall_comm + +alias ⟨IsEquiv.lt_iff_lt, _⟩ := isEquiv_iff_val_lt_val + theorem isEquiv_of_val_le_one [LinearOrderedCommGroupWithZero Γ₀] [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) (h : ∀ {x : K}, v x ≤ 1 ↔ v' x ≤ 1) : v.IsEquiv v' := by From 0c560e41dcf966b36f67d5e647bada2b9aa3a72b Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Mon, 23 Sep 2024 13:56:36 +0000 Subject: [PATCH 092/170] chore(Data/Finset): move non-lattice lemma out of lattice file (#17048) This lemma doesn't require finset lattice machinery to prove, and is out-of-place in its current location. Thus, we move it alongside other `Finset.range` lemmas. This is in part so that this lemma can be used without importing more of mathlib, and in part to help with a split of the lattice file, which would leave this particular lemma essentially homeless. --- Mathlib/Data/Finset/Basic.lean | 4 ++++ Mathlib/Data/Finset/Lattice.lean | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index 142100db3baa1..d979c5a475c1c 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -2597,6 +2597,10 @@ lemma range_nontrivial {n : ℕ} (hn : 1 < n) : (Finset.range n).Nontrivial := b rw [Finset.Nontrivial, Finset.coe_range] exact ⟨0, Nat.zero_lt_one.trans hn, 1, hn, Nat.zero_ne_one⟩ +theorem exists_nat_subset_range (s : Finset ℕ) : ∃ n : ℕ, s ⊆ range n := + s.induction_on (by simp) + fun a s _ ⟨n, hn⟩ => ⟨max (a + 1) n, insert_subset (by simp) (hn.trans (by simp))⟩ + end Range -- useful rules for calculations with quantifiers diff --git a/Mathlib/Data/Finset/Lattice.lean b/Mathlib/Data/Finset/Lattice.lean index cc7f493f2efbc..3efa17777c830 100644 --- a/Mathlib/Data/Finset/Lattice.lean +++ b/Mathlib/Data/Finset/Lattice.lean @@ -204,9 +204,6 @@ theorem _root_.List.foldr_sup_eq_sup_toFinset [DecidableEq α] (l : List α) : theorem subset_range_sup_succ (s : Finset ℕ) : s ⊆ range (s.sup id).succ := fun _ hn => mem_range.2 <| Nat.lt_succ_of_le <| @le_sup _ _ _ _ _ id _ hn -theorem exists_nat_subset_range (s : Finset ℕ) : ∃ n : ℕ, s ⊆ range n := - ⟨_, s.subset_range_sup_succ⟩ - theorem sup_induction {p : α → Prop} (hb : p ⊥) (hp : ∀ a₁, p a₁ → ∀ a₂, p a₂ → p (a₁ ⊔ a₂)) (hs : ∀ b ∈ s, p (f b)) : p (s.sup f) := by induction s using Finset.cons_induction with From 9c7175d4868d3add31b7e02c298308776edc1762 Mon Sep 17 00:00:00 2001 From: Jack McKoen Date: Mon, 23 Sep 2024 14:47:27 +0000 Subject: [PATCH 093/170] feat(CategoryTheory): `MonoidalClosed` instance on functors to `Type` (#13710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR defines an instance of `MonoidalClosed` on `C ⥤ Type max w v u` where `C : Type u` with `[Category.{v} C]`, and `w` is an arbitrary universe. An explicit internal hom functor is constructed, and is proved to be a right adjoint to `tensorLeft`. Co-authored-by: Jack <104791831+mckoen@users.noreply.github.com> Co-authored-by: Kim Morrison --- Mathlib.lean | 1 + .../CategoryTheory/Closed/FunctorToTypes.lean | 68 +++++++++++++++++++ .../CategoryTheory/Functor/FunctorHom.lean | 3 + 3 files changed, 72 insertions(+) create mode 100644 Mathlib/CategoryTheory/Closed/FunctorToTypes.lean diff --git a/Mathlib.lean b/Mathlib.lean index 35810d46201d8..064cc2f6fc197 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1450,6 +1450,7 @@ import Mathlib.CategoryTheory.ChosenFiniteProducts.FunctorCategory import Mathlib.CategoryTheory.Closed.Cartesian import Mathlib.CategoryTheory.Closed.Functor import Mathlib.CategoryTheory.Closed.FunctorCategory +import Mathlib.CategoryTheory.Closed.FunctorToTypes import Mathlib.CategoryTheory.Closed.Ideal import Mathlib.CategoryTheory.Closed.Monoidal import Mathlib.CategoryTheory.Closed.Types diff --git a/Mathlib/CategoryTheory/Closed/FunctorToTypes.lean b/Mathlib/CategoryTheory/Closed/FunctorToTypes.lean new file mode 100644 index 0000000000000..35a8c0eccbad2 --- /dev/null +++ b/Mathlib/CategoryTheory/Closed/FunctorToTypes.lean @@ -0,0 +1,68 @@ +/- +Copyright (c) 2024 Jack McKoen. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jack McKoen +-/ +import Mathlib.CategoryTheory.Functor.FunctorHom +import Mathlib.CategoryTheory.Closed.Monoidal + +/-! +# Functors to Type are closed. + +Show that `C ⥤ Type max w v u` is monoidal closed for `C` a category in `Type u` with morphisms in +`Type v`, and `w` an arbitrary universe. + +## TODO +It should be shown that `C ⥤ Type max w v u` is cartesian closed. + +-/ + + +universe w v' v u u' + +open CategoryTheory Functor MonoidalCategory + +namespace CategoryTheory.FunctorToTypes + +variable {C : Type u} [Category.{v} C] {D : Type u'} [Category.{v'} D] + +variable (F : C ⥤ Type max w v u) + +/-- When `F G H : C ⥤ Type max w v u`, we have `(G ⟶ F.functorHom H) ≃ (F ⊗ G ⟶ H)`. -/ +@[simps!] +def functorHomEquiv (G H : C ⥤ Type max w v u) : (G ⟶ F.functorHom H) ≃ (F ⊗ G ⟶ H) := + (Functor.functorHomEquiv F H G).trans (homObjEquiv F H G) + +/-- Given a morphism `f : G ⟶ H`, an object `c : C`, and an element of `(F.functorHom G).obj c`, +construct an element of `(F.functorHom H).obj c`. -/ +@[simps] +def rightAdj_map {F G H : C ⥤ Type max w v u} (f : G ⟶ H) (c : C) (a : (F.functorHom G).obj c) : + (F.functorHom H).obj c where + app d b := a.app d b ≫ f.app d + naturality g h := by + have := a.naturality g h + change (F.map g ≫ a.app _ (h ≫ g)) ≫ _ = _ + aesop + +/-- A right adjoint of `tensorLeft F`. -/ +@[simps!] +def rightAdj : (C ⥤ Type max w v u) ⥤ C ⥤ Type max w v u where + obj G := F.functorHom G + map f := { app := rightAdj_map f } + +/-- The adjunction `tensorLeft F ⊣ rightAdj F`. -/ +def adj : tensorLeft F ⊣ rightAdj F where + unit := { + app := fun G ↦ (functorHomEquiv F G _).2 (𝟙 _) + naturality := fun G H f ↦ by + dsimp [rightAdj] + ext _ + simp [FunctorToTypes.naturality] } + counit := { app := fun G ↦ functorHomEquiv F _ G (𝟙 _) } + +instance closed : Closed F where + adj := adj F + +instance monoidalClosed : MonoidalClosed (C ⥤ Type max w v u) where + +end CategoryTheory.FunctorToTypes diff --git a/Mathlib/CategoryTheory/Functor/FunctorHom.lean b/Mathlib/CategoryTheory/Functor/FunctorHom.lean index af550df60805c..bd8ab6a9e031e 100644 --- a/Mathlib/CategoryTheory/Functor/FunctorHom.lean +++ b/Mathlib/CategoryTheory/Functor/FunctorHom.lean @@ -41,6 +41,7 @@ structure HomObj (A : C ⥤ Type w) where /-- When `F`, `G`, and `A` are all functors `C ⥤ Type w`, then `HomObj F G A` is in bijection with `F ⊗ A ⟶ G`. -/ +@[simps] def homObjEquiv (F G A : C ⥤ Type w) : (HomObj F G A) ≃ (F ⊗ A ⟶ G) where toFun a := ⟨fun X ⟨x, y⟩ ↦ a.app X y x, fun X Y f ↦ by ext ⟨x, y⟩ @@ -87,6 +88,7 @@ def map {A' : C ⥤ Type w} (f : A' ⟶ A) (x : HomObj F G A) : HomObj F G A' wh end HomObj /-- The contravariant functor taking `A : C ⥤ Type w` to `HomObj F G A`, i.e. Hom(F ⊗ -, G). -/ +@[simps] def homObjFunctor : (C ⥤ Type w)ᵒᵖ ⥤ Type max w v' u where obj A := HomObj F G A.unop map {A A'} f x := @@ -109,6 +111,7 @@ lemma functorHom_ext {X : C} {x y : (F.functorHom G).obj X} HomObj.ext (by ext; apply h) /-- The equivalence `(A ⟶ F.functorHom G) ≃ HomObj F G A`. -/ +@[simps] def functorHomEquiv (A : C ⥤ Type max u v v') : (A ⟶ F.functorHom G) ≃ HomObj F G A where toFun φ := { app := fun X a ↦ (φ.app X a).app X (𝟙 _) From 305ddf1349def3aa813838a62f73592b81759784 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Jie Rui Date: Mon, 23 Sep 2024 14:56:15 +0000 Subject: [PATCH 094/170] feat: maximal upper/minimal lower bounds of finset elements (#16970) Originally motivated by the Carleson project. We rename `Finite.exists_ge_minimal` to `Finite.exists_minimal_le` and add `Finset` and `Set.Finite` versions. --- Mathlib/Data/Fintype/Order.lean | 32 +++++++++++++++++++++++++++----- Mathlib/Order/Minimal.lean | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Mathlib/Data/Fintype/Order.lean b/Mathlib/Data/Fintype/Order.lean index 93fb8dff25530..6fa3b6c7e32fd 100644 --- a/Mathlib/Data/Fintype/Order.lean +++ b/Mathlib/Data/Fintype/Order.lean @@ -156,15 +156,37 @@ end Fintype /-! ### Properties for PartialOrders -/ -lemma Finite.exists_ge_minimal {α} [Finite α] [PartialOrder α] {a : α} {p : α → Prop} (h : p a) : - ∃ b, b ≤ a ∧ Minimal p b := by +section PartialOrder + +variable {α : Type*} [PartialOrder α] {a : α} {p : α → Prop} + +lemma Finite.exists_minimal_le [Finite α] (h : p a) : ∃ b, b ≤ a ∧ Minimal p b := by obtain ⟨b, ⟨hba, hb⟩, hbmin⟩ := Set.Finite.exists_minimal_wrt id {x | x ≤ a ∧ p x} (Set.toFinite _) ⟨a, rfl.le, h⟩ exact ⟨b, hba, hb, fun x hx hxb ↦ (hbmin x ⟨hxb.trans hba, hx⟩ hxb).le⟩ -lemma Finite.exists_le_maximal {α} [Finite α] [PartialOrder α] {a : α} {p : α → Prop} (h : p a) : - ∃ b, a ≤ b ∧ Maximal p b := - Finite.exists_ge_minimal (α := αᵒᵈ) h +@[deprecated (since := "2024-09-23")] alias Finite.exists_ge_minimal := Finite.exists_minimal_le + +lemma Finite.exists_le_maximal [Finite α] (h : p a) : ∃ b, a ≤ b ∧ Maximal p b := + Finite.exists_minimal_le (α := αᵒᵈ) h + +lemma Finset.exists_minimal_le (s : Finset α) (h : a ∈ s) : ∃ b, b ≤ a ∧ Minimal (· ∈ s) b := by + obtain ⟨⟨b, _⟩, lb, minb⟩ := @Finite.exists_minimal_le s _ ⟨a, h⟩ (·.1 ∈ s) _ h + use b, lb; rwa [minimal_subtype, inf_idem] at minb + +lemma Finset.exists_le_maximal (s : Finset α) (h : a ∈ s) : ∃ b, a ≤ b ∧ Maximal (· ∈ s) b := + s.exists_minimal_le (α := αᵒᵈ) h + +lemma Set.Finite.exists_minimal_le {s : Set α} (hs : s.Finite) (h : a ∈ s) : + ∃ b, b ≤ a ∧ Minimal (· ∈ s) b := by + obtain ⟨b, lb, minb⟩ := hs.toFinset.exists_minimal_le (hs.mem_toFinset.mpr h) + use b, lb; simpa using minb + +lemma Set.Finite.exists_le_maximal {s : Set α} (hs : s.Finite) (h : a ∈ s) : + ∃ b, a ≤ b ∧ Maximal (· ∈ s) b := + hs.exists_minimal_le (α := αᵒᵈ) h + +end PartialOrder /-! ### Concrete instances -/ diff --git a/Mathlib/Order/Minimal.lean b/Mathlib/Order/Minimal.lean index eec9b8aea31ce..728087a7dbdf4 100644 --- a/Mathlib/Order/Minimal.lean +++ b/Mathlib/Order/Minimal.lean @@ -381,7 +381,7 @@ variable [Preorder α] theorem setOf_minimal_subset (s : Set α) : {x | Minimal (· ∈ s) x} ⊆ s := sep_subset .. -theorem setOf_maximal_subset (s : Set α) : {x | Minimal (· ∈ s) x} ⊆ s := +theorem setOf_maximal_subset (s : Set α) : {x | Maximal (· ∈ s) x} ⊆ s := sep_subset .. theorem Set.Subsingleton.maximal_mem_iff (h : s.Subsingleton) : Maximal (· ∈ s) x ↔ x ∈ s := by From 2aa39ca434a3c20369b7d68706abde3e47d327cb Mon Sep 17 00:00:00 2001 From: Jz Pan Date: Mon, 23 Sep 2024 15:47:58 +0000 Subject: [PATCH 095/170] feat: add `map_i[I]nf` for sub(semi)ring, subalgebra, subfield etc. (#15113) ... which require that the map in question is injective (this automatically holds for fields). Added for: - sub(semi)group, submonoid, and their additive counterpart - sub(semi)ring, (star)subalgebra, and their non-unital counterpart - subfield and intermediate fields. Also add `(coe|mem)_iInf` for subfield and (non-unital)subsemiring. --- .../Algebra/Algebra/NonUnitalSubalgebra.lean | 12 ++++++++++++ Mathlib/Algebra/Algebra/Subalgebra/Basic.lean | 8 ++++++++ Mathlib/Algebra/Field/Subfield.lean | 15 +++++++++++++++ Mathlib/Algebra/Group/Subgroup/Basic.lean | 10 ++++++++++ .../Algebra/Group/Submonoid/Operations.lean | 10 ++++++++++ .../Group/Subsemigroup/Operations.lean | 10 ++++++++++ Mathlib/Algebra/Ring/Subring/Basic.lean | 8 ++++++++ Mathlib/Algebra/Ring/Subsemiring/Basic.lean | 15 +++++++++++++++ Mathlib/Algebra/Star/NonUnitalSubalgebra.lean | 12 ++++++++++++ Mathlib/Algebra/Star/Subalgebra.lean | 8 ++++++++ Mathlib/FieldTheory/Adjoin.lean | 8 ++++++++ .../RingTheory/NonUnitalSubring/Basic.lean | 8 ++++++++ .../NonUnitalSubsemiring/Basic.lean | 19 +++++++++++++++++++ 13 files changed, 143 insertions(+) diff --git a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean index ce534b664d2fa..d7beda182c549 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean @@ -726,6 +726,11 @@ theorem map_sup [IsScalarTower R B B] [SMulCommClass R B B] ((S ⊔ T).map f : NonUnitalSubalgebra R B) = S.map f ⊔ T.map f := (NonUnitalSubalgebra.gc_map_comap f).l_sup +theorem map_inf [IsScalarTower R B B] [SMulCommClass R B B] + (f : F) (hf : Function.Injective f) (S T : NonUnitalSubalgebra R A) : + ((S ⊓ T).map f : NonUnitalSubalgebra R B) = S.map f ⊓ T.map f := + SetLike.coe_injective (Set.image_inter hf) + @[simp, norm_cast] theorem coe_inf (S T : NonUnitalSubalgebra R A) : (↑(S ⊓ T) : Set A) = (S : Set A) ∩ T := rfl @@ -768,6 +773,13 @@ theorem coe_iInf {ι : Sort*} {S : ι → NonUnitalSubalgebra R A} : theorem mem_iInf {ι : Sort*} {S : ι → NonUnitalSubalgebra R A} {x : A} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by simp only [iInf, mem_sInf, Set.forall_mem_range] +theorem map_iInf {ι : Sort*} [Nonempty ι] + [IsScalarTower R B B] [SMulCommClass R B B] (f : F) + (hf : Function.Injective f) (S : ι → NonUnitalSubalgebra R A) : + ((⨅ i, S i).map f : NonUnitalSubalgebra R B) = ⨅ i, (S i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ S) + @[simp] theorem iInf_toSubmodule {ι : Sort*} (S : ι → NonUnitalSubalgebra R A) : (⨅ i, S i).toSubmodule = ⨅ i, (S i).toSubmodule := diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index 854c9922cd13d..311a49067acad 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -678,6 +678,9 @@ theorem mul_mem_sup {S T : Subalgebra R A} {x y : A} (hx : x ∈ S) (hy : y ∈ theorem map_sup (f : A →ₐ[R] B) (S T : Subalgebra R A) : (S ⊔ T).map f = S.map f ⊔ T.map f := (Subalgebra.gc_map_comap f).l_sup +theorem map_inf (f : A →ₐ[R] B) (hf : Function.Injective f) (S T : Subalgebra R A) : + (S ⊓ T).map f = S.map f ⊓ T.map f := SetLike.coe_injective (Set.image_inter hf) + @[simp, norm_cast] theorem coe_inf (S T : Subalgebra R A) : (↑(S ⊓ T) : Set A) = (S ∩ T : Set A) := rfl @@ -718,6 +721,11 @@ theorem coe_iInf {ι : Sort*} {S : ι → Subalgebra R A} : (↑(⨅ i, S i) : S theorem mem_iInf {ι : Sort*} {S : ι → Subalgebra R A} {x : A} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by simp only [iInf, mem_sInf, Set.forall_mem_range] +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : A →ₐ[R] B) (hf : Function.Injective f) + (s : ι → Subalgebra R A) : (iInf s).map f = ⨅ (i : ι), (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + open Subalgebra in @[simp] theorem iInf_toSubmodule {ι : Sort*} (S : ι → Subalgebra R A) : diff --git a/Mathlib/Algebra/Field/Subfield.lean b/Mathlib/Algebra/Field/Subfield.lean index 8d57654e441ac..63adf4ac50a55 100644 --- a/Mathlib/Algebra/Field/Subfield.lean +++ b/Mathlib/Algebra/Field/Subfield.lean @@ -545,6 +545,13 @@ theorem mem_sInf {S : Set (Subfield K)} {x : K} : x ∈ sInf S ↔ ∀ p ∈ S, Subring.mem_sInf.trans ⟨fun h p hp => h p.toSubring ⟨p, hp, rfl⟩, fun h _ ⟨p', hp', p_eq⟩ => p_eq ▸ h p' hp'⟩ +@[simp, norm_cast] +theorem coe_iInf {ι : Sort*} {S : ι → Subfield K} : (↑(⨅ i, S i) : Set K) = ⋂ i, S i := by + simp only [iInf, coe_sInf, Set.biInter_range] + +theorem mem_iInf {ι : Sort*} {S : ι → Subfield K} {x : K} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by + simp only [iInf, mem_sInf, Set.forall_mem_range] + @[simp] theorem sInf_toSubring (s : Set (Subfield K)) : (sInf s).toSubring = ⨅ t ∈ s, Subfield.toSubring t := by @@ -659,6 +666,14 @@ theorem map_iSup {ι : Sort*} (f : K →+* L) (s : ι → Subfield K) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +theorem map_inf (s t : Subfield K) (f : K →+* L) : (s ⊓ t).map f = s.map f ⊓ t.map f := + SetLike.coe_injective (Set.image_inter f.injective) + +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : K →+* L) (s : ι → Subfield K) : + (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective f.injective).image_iInter_eq (s := SetLike.coe ∘ s) + theorem comap_inf (s t : Subfield L) (f : K →+* L) : (s ⊓ t).comap f = s.comap f ⊓ t.comap f := (gc_map_comap f).u_inf diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index 7881c95bcec47..9a542a9b6014d 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -1205,6 +1205,16 @@ theorem map_iSup {ι : Sort*} (f : G →* N) (s : ι → Subgroup G) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +@[to_additive] +theorem map_inf (H K : Subgroup G) (f : G →* N) (hf : Function.Injective f) : + (H ⊓ K).map f = H.map f ⊓ K.map f := SetLike.coe_injective (Set.image_inter hf) + +@[to_additive] +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : G →* N) (hf : Function.Injective f) + (s : ι → Subgroup G) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + @[to_additive] theorem comap_sup_comap_le (H K : Subgroup N) (f : G →* N) : comap f H ⊔ comap f K ≤ comap f (H ⊔ K) := diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index e410115baf4ec..a0ee1b9441d79 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -274,6 +274,16 @@ theorem map_sup (S T : Submonoid M) (f : F) : (S ⊔ T).map f = S.map f ⊔ T.ma theorem map_iSup {ι : Sort*} (f : F) (s : ι → Submonoid M) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f : GaloisConnection (map f) (comap f)).l_iSup +@[to_additive] +theorem map_inf (S T : Submonoid M) (f : F) (hf : Function.Injective f) : + (S ⊓ T).map f = S.map f ⊓ T.map f := SetLike.coe_injective (Set.image_inter hf) + +@[to_additive] +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : F) (hf : Function.Injective f) + (s : ι → Submonoid M) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + @[to_additive] theorem comap_inf (S T : Submonoid N) (f : F) : (S ⊓ T).comap f = S.comap f ⊓ T.comap f := (gc_map_comap f : GaloisConnection (map f) (comap f)).u_inf diff --git a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean index 4f86ed34a4d25..05de353785319 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean @@ -278,6 +278,16 @@ theorem map_iSup {ι : Sort*} (f : M →ₙ* N) (s : ι → Subsemigroup M) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +@[to_additive] +theorem map_inf (S T : Subsemigroup M) (f : M →ₙ* N) (hf : Function.Injective f) : + (S ⊓ T).map f = S.map f ⊓ T.map f := SetLike.coe_injective (Set.image_inter hf) + +@[to_additive] +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : M →ₙ* N) (hf : Function.Injective f) + (s : ι → Subsemigroup M) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + @[to_additive] theorem comap_inf (S T : Subsemigroup N) (f : M →ₙ* N) : (S ⊓ T).comap f = S.comap f ⊓ T.comap f := (gc_map_comap f).u_inf diff --git a/Mathlib/Algebra/Ring/Subring/Basic.lean b/Mathlib/Algebra/Ring/Subring/Basic.lean index c93d933e50864..dece9ec6923b9 100644 --- a/Mathlib/Algebra/Ring/Subring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subring/Basic.lean @@ -897,6 +897,14 @@ theorem map_iSup {ι : Sort*} (f : R →+* S) (s : ι → Subring R) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +theorem map_inf (s t : Subring R) (f : R →+* S) (hf : Function.Injective f) : + (s ⊓ t).map f = s.map f ⊓ t.map f := SetLike.coe_injective (Set.image_inter hf) + +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : R →+* S) (hf : Function.Injective f) + (s : ι → Subring R) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + theorem comap_inf (s t : Subring S) (f : R →+* S) : (s ⊓ t).comap f = s.comap f ⊓ t.comap f := (gc_map_comap f).u_inf diff --git a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean index 72f996c586990..03dc4ba71c416 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean @@ -500,6 +500,13 @@ theorem coe_sInf (S : Set (Subsemiring R)) : ((sInf S : Subsemiring R) : Set R) theorem mem_sInf {S : Set (Subsemiring R)} {x : R} : x ∈ sInf S ↔ ∀ p ∈ S, x ∈ p := Set.mem_iInter₂ +@[simp, norm_cast] +theorem coe_iInf {ι : Sort*} {S : ι → Subsemiring R} : (↑(⨅ i, S i) : Set R) = ⋂ i, S i := by + simp only [iInf, coe_sInf, Set.biInter_range] + +theorem mem_iInf {ι : Sort*} {S : ι → Subsemiring R} {x : R} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by + simp only [iInf, mem_sInf, Set.forall_mem_range] + @[simp] theorem sInf_toSubmonoid (s : Set (Subsemiring R)) : (sInf s).toSubmonoid = ⨅ t ∈ s, Subsemiring.toSubmonoid t := @@ -835,6 +842,14 @@ theorem map_iSup {ι : Sort*} (f : R →+* S) (s : ι → Subsemiring R) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +theorem map_inf (s t : Subsemiring R) (f : R →+* S) (hf : Function.Injective f) : + (s ⊓ t).map f = s.map f ⊓ t.map f := SetLike.coe_injective (Set.image_inter hf) + +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : R →+* S) (hf : Function.Injective f) + (s : ι → Subsemiring R) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + theorem comap_inf (s t : Subsemiring S) (f : R →+* S) : (s ⊓ t).comap f = s.comap f ⊓ t.comap f := (gc_map_comap f).u_inf diff --git a/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean b/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean index 88ae6784d80a8..61e7ac629195f 100644 --- a/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean +++ b/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean @@ -733,6 +733,11 @@ theorem map_sup [IsScalarTower R B B] [SMulCommClass R B B] [StarModule R B] (f ((S ⊔ T).map f : NonUnitalStarSubalgebra R B) = S.map f ⊔ T.map f := (NonUnitalStarSubalgebra.gc_map_comap f).l_sup +theorem map_inf [IsScalarTower R B B] [SMulCommClass R B B] [StarModule R B] (f : F) + (hf : Function.Injective f) (S T : NonUnitalStarSubalgebra R A) : + ((S ⊓ T).map f : NonUnitalStarSubalgebra R B) = S.map f ⊓ T.map f := + SetLike.coe_injective (Set.image_inter hf) + @[simp, norm_cast] theorem coe_inf (S T : NonUnitalStarSubalgebra R A) : (↑(S ⊓ T) : Set A) = (S : Set A) ∩ T := rfl @@ -766,6 +771,13 @@ theorem coe_iInf {ι : Sort*} {S : ι → NonUnitalStarSubalgebra R A} : theorem mem_iInf {ι : Sort*} {S : ι → NonUnitalStarSubalgebra R A} {x : A} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by simp only [iInf, mem_sInf, Set.forall_mem_range] +theorem map_iInf {ι : Sort*} [Nonempty ι] + [IsScalarTower R B B] [SMulCommClass R B B] [StarModule R B] (f : F) + (hf : Function.Injective f) (S : ι → NonUnitalStarSubalgebra R A) : + ((⨅ i, S i).map f : NonUnitalStarSubalgebra R B) = ⨅ i, (S i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ S) + @[simp] theorem iInf_toNonUnitalSubalgebra {ι : Sort*} (S : ι → NonUnitalStarSubalgebra R A) : (⨅ i, S i).toNonUnitalSubalgebra = ⨅ i, (S i).toNonUnitalSubalgebra := diff --git a/Mathlib/Algebra/Star/Subalgebra.lean b/Mathlib/Algebra/Star/Subalgebra.lean index 2de08d5c7ac4d..b0dc2097f565e 100644 --- a/Mathlib/Algebra/Star/Subalgebra.lean +++ b/Mathlib/Algebra/Star/Subalgebra.lean @@ -594,6 +594,9 @@ theorem mul_mem_sup {S T : StarSubalgebra R A} {x y : A} (hx : x ∈ S) (hy : y theorem map_sup (f : A →⋆ₐ[R] B) (S T : StarSubalgebra R A) : map f (S ⊔ T) = map f S ⊔ map f T := (StarSubalgebra.gc_map_comap f).l_sup +theorem map_inf (f : A →⋆ₐ[R] B) (hf : Function.Injective f) (S T : StarSubalgebra R A) : + map f (S ⊓ T) = map f S ⊓ map f T := SetLike.coe_injective (Set.image_inter hf) + @[simp, norm_cast] theorem coe_inf (S T : StarSubalgebra R A) : (↑(S ⊓ T) : Set A) = (S : Set A) ∩ T := rfl @@ -627,6 +630,11 @@ theorem coe_iInf {ι : Sort*} {S : ι → StarSubalgebra R A} : (↑(⨅ i, S i) theorem mem_iInf {ι : Sort*} {S : ι → StarSubalgebra R A} {x : A} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by simp only [iInf, mem_sInf, Set.forall_mem_range] +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : A →⋆ₐ[R] B) (hf : Function.Injective f) + (s : ι → StarSubalgebra R A) : map f (iInf s) = ⨅ (i : ι), map f (s i) := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + @[simp] theorem iInf_toSubalgebra {ι : Sort*} (S : ι → StarSubalgebra R A) : (⨅ i, S i).toSubalgebra = ⨅ i, (S i).toSubalgebra := diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index 525d7d0c62b82..07881787d2645 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -252,6 +252,14 @@ theorem map_iSup {ι : Sort*} (f : E →ₐ[F] K) (s : ι → IntermediateField (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +theorem map_inf (s t : IntermediateField F E) (f : E →ₐ[F] K) : + (s ⊓ t).map f = s.map f ⊓ t.map f := SetLike.coe_injective (Set.image_inter f.injective) + +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : E →ₐ[F] K) (s : ι → IntermediateField F E) : + (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective f.injective).image_iInter_eq (s := SetLike.coe ∘ s) + theorem _root_.AlgHom.fieldRange_eq_map (f : E →ₐ[F] K) : f.fieldRange = IntermediateField.map f ⊤ := SetLike.ext' Set.image_univ.symm diff --git a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean index 3d5642917f222..69c9fcd2931b4 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean @@ -800,6 +800,14 @@ theorem map_iSup {ι : Sort*} (f : F) (s : ι → NonUnitalSubring R) : (iSup s).map f = ⨆ i, (s i).map f := (gc_map_comap f).l_iSup +theorem map_inf (s t : NonUnitalSubring R) (f : F) (hf : Function.Injective f) : + (s ⊓ t).map f = s.map f ⊓ t.map f := SetLike.coe_injective (Set.image_inter hf) + +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : F) (hf : Function.Injective f) + (s : ι → NonUnitalSubring R) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + theorem comap_inf (s t : NonUnitalSubring S) (f : F) : (s ⊓ t).comap f = s.comap f ⊓ t.comap f := (gc_map_comap f).u_inf diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean index 3e465645af7db..55bb7d2fd0d44 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean @@ -379,6 +379,15 @@ theorem coe_sInf (S : Set (NonUnitalSubsemiring R)) : theorem mem_sInf {S : Set (NonUnitalSubsemiring R)} {x : R} : x ∈ sInf S ↔ ∀ p ∈ S, x ∈ p := Set.mem_iInter₂ +@[simp, norm_cast] +theorem coe_iInf {ι : Sort*} {S : ι → NonUnitalSubsemiring R} : + (↑(⨅ i, S i) : Set R) = ⋂ i, S i := by + simp only [iInf, coe_sInf, Set.biInter_range] + +theorem mem_iInf {ι : Sort*} {S : ι → NonUnitalSubsemiring R} {x : R} : + (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by + simp only [iInf, mem_sInf, Set.forall_mem_range] + @[simp] theorem sInf_toSubsemigroup (s : Set (NonUnitalSubsemiring R)) : (sInf s).toSubsemigroup = ⨅ t ∈ s, NonUnitalSubsemiring.toSubsemigroup t := @@ -670,6 +679,16 @@ theorem map_iSup {ι : Sort*} (f : F) (s : ι → NonUnitalSubsemiring R) : (map f (iSup s) : NonUnitalSubsemiring S) = ⨆ i, map f (s i) := @GaloisConnection.l_iSup _ _ _ _ _ _ _ (gc_map_comap f) s +theorem map_inf (s t : NonUnitalSubsemiring R) (f : F) (hf : Function.Injective f) : + (map f (s ⊓ t) : NonUnitalSubsemiring S) = map f s ⊓ map f t := + SetLike.coe_injective (Set.image_inter hf) + +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : F) (hf : Function.Injective f) + (s : ι → NonUnitalSubsemiring R) : + (map f (iInf s) : NonUnitalSubsemiring S) = ⨅ i, map f (s i) := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + theorem comap_inf (s t : NonUnitalSubsemiring S) (f : F) : (comap f (s ⊓ t) : NonUnitalSubsemiring R) = comap f s ⊓ comap f t := @GaloisConnection.u_inf _ _ s t _ _ _ _ (gc_map_comap f) From 7e018486b4203cc634081ac04068ee0bd8c25ac8 Mon Sep 17 00:00:00 2001 From: Xavier Roblot <46200072+xroblot@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:51:21 +0000 Subject: [PATCH 096/170] feat(NumberField/CanonicalEmbedding/FundamentalCone): Prove equivalence with principal ideals (#12333) We prove that there is an equiv between the nonzero integral points in the fundamental cone and the nonzero integral ideals of `K` and that this equiv preserves norm. This PR is part of the proof of the Analytic Class Number Formula. Co-authored-by: Xavier Roblot --- .../CanonicalEmbedding/FundamentalCone.lean | 169 +++++++++++++++++- 1 file changed, 167 insertions(+), 2 deletions(-) diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean index 3421bbbf4d554..911bb6fc07048 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Xavier Roblot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Xavier Roblot -/ +import Mathlib.RingTheory.Ideal.IsPrincipal import Mathlib.NumberTheory.NumberField.Units.DirichletTheorem /-! @@ -25,6 +26,14 @@ domain for the action of `(𝓞 K)ˣ` modulo torsion, see `exists_unit_smul_mem` * `NumberField.mixedEmbedding.fundamentalCone.integralPoint`: the subset of elements of the fundamental cone that are images of algebraic integers of `K`. +* `NumberField.mixedEmbedding.fundamentalCone.integralPointEquiv`: the equivalence between +`fundamentalCone.integralPoint K` and the principal nonzero ideals of `𝓞 K` times the +torsion of `K`. + +* `NumberField.mixedEmbedding.fundamentalCone.card_isPrincipal_norm_eq_mul_torsion`: the number of +principal nonzero ideals in `𝓞 K` of norm `n` multiplied by the order of the torsion of `K` is +equal to the number of `fundamentalCone.integralPoint K` of norm `n`. + ## Tags number field, canonical embedding, units, principal ideals @@ -262,8 +271,10 @@ theorem integralPoint_ne_zero (a : integralPoint K) : (a : mixedSpace K) ≠ 0 open scoped nonZeroDivisors -/-- For `a : integralPoint K`, the unique nonzero algebraic integer whose image by -`mixedEmbedding` is equal to `a`, see `mixedEmbedding_preimageOfIntegralPoint`. -/ +/-- For `a : fundamentalCone K`, the unique nonzero algebraic integer `x` such that its image by +`mixedEmbedding` is equal to `a`. Note that we state the fact that `x ≠ 0` by saying that `x` is +a nonzero divisors since we will use later on the isomorphism +`Ideal.associatesNonZeroDivisorsEquivIsPrincipal`, see `integralPointEquiv`. -/ def preimageOfIntegralPoint (a : integralPoint K) : (𝓞 K)⁰ := ⟨(mem_integralPoint.mp a.prop).2.choose, mem_nonZeroDivisors_of_ne_zero (by simp_rw [ne_eq, ← RingOfIntegers.coe_injective.eq_iff, ← (mixedEmbedding_injective K).eq_iff, @@ -330,6 +341,160 @@ def quotIntNorm : @[simp] theorem quotIntNorm_apply (a : integralPoint K) : quotIntNorm ⟦a⟧ = intNorm a := rfl +variable (K) in +/-- The map that sends an element of `a : integralPoint K` to the associates class +of its preimage in `(𝓞 K)⁰`. By quotienting by the kernel of the map, which is equal to the +subgroup of torsion, we get the equivalence `integralPointQuotEquivAssociates`. -/ +def integralPointToAssociates (a : integralPoint K) : Associates (𝓞 K)⁰ := + ⟦preimageOfIntegralPoint a⟧ + +@[simp] +theorem integralPointToAssociates_apply (a : integralPoint K) : + integralPointToAssociates K a = ⟦preimageOfIntegralPoint a⟧ := rfl + +variable (K) in +theorem integralPointToAssociates_surjective : + Function.Surjective (integralPointToAssociates K) := by + rintro ⟨x⟩ + obtain ⟨u, hu⟩ : ∃ u : (𝓞 K)ˣ, u • mixedEmbedding K (x : 𝓞 K) ∈ integralPoint K := by + refine exists_unitSMul_mem_integralPoint ?_ ⟨(x : 𝓞 K), Set.mem_range_self _, rfl⟩ + exact (map_ne_zero _).mpr <| RingOfIntegers.coe_ne_zero_iff.mpr (nonZeroDivisors.coe_ne_zero _) + refine ⟨⟨u • mixedEmbedding K (x : 𝓞 K), hu⟩, + Quotient.sound ⟨unitsNonZeroDivisorsEquiv.symm u⁻¹, ?_⟩⟩ + simp_rw [Subtype.ext_iff, RingOfIntegers.ext_iff, ← (mixedEmbedding_injective K).eq_iff, + Submonoid.coe_mul, map_mul, mixedEmbedding_preimageOfIntegralPoint, + unitSMul_smul, ← map_mul, mul_comm, map_inv, val_inv_unitsNonZeroDivisorsEquiv_symm_apply_coe, + Units.mul_inv_cancel_right] + +theorem integralPointToAssociates_eq_iff (a b : integralPoint K) : + integralPointToAssociates K a = integralPointToAssociates K b ↔ + ∃ ζ : torsion K, ζ • a = b := by + simp_rw [integralPointToAssociates_apply, Associates.quotient_mk_eq_mk, + Associates.mk_eq_mk_iff_associated, Associated, mul_comm, Subtype.ext_iff, + RingOfIntegers.ext_iff, ← (mixedEmbedding_injective K).eq_iff, Submonoid.coe_mul, map_mul, + mixedEmbedding_preimageOfIntegralPoint, integralPoint_torsionSMul_smul_coe] + refine ⟨fun ⟨u, h⟩ ↦ ⟨⟨unitsNonZeroDivisorsEquiv u, ?_⟩, by simpa using h⟩, + fun ⟨⟨u, _⟩, h⟩ ↦ ⟨unitsNonZeroDivisorsEquiv.symm u, by simpa using h⟩⟩ + exact (unit_smul_mem_iff_mem_torsion a.prop.1 _).mp (by simpa [h] using b.prop.1) + +variable (K) in +/-- The equivalence between `integralPoint K` modulo `torsion K` and `Associates (𝓞 K)⁰`. -/ +def integralPointQuotEquivAssociates : + Quotient (MulAction.orbitRel (torsion K) (integralPoint K)) ≃ Associates (𝓞 K)⁰ := + Equiv.ofBijective + (Quotient.lift (integralPointToAssociates K) + fun _ _ h ↦ ((integralPointToAssociates_eq_iff _ _).mpr h).symm) + ⟨by convert Setoid.ker_lift_injective (integralPointToAssociates K) + all_goals + · ext a b + rw [Setoid.ker_def, eq_comm, integralPointToAssociates_eq_iff b a, + MulAction.orbitRel_apply, MulAction.mem_orbit_iff], + (Quot.surjective_lift _).mpr (integralPointToAssociates_surjective K)⟩ + +@[simp] +theorem integralPointQuotEquivAssociates_apply (a : integralPoint K) : + integralPointQuotEquivAssociates K ⟦a⟧ = ⟦preimageOfIntegralPoint a⟧ := rfl + +theorem integralPoint_torsionSMul_stabilizer (a : integralPoint K) : + MulAction.stabilizer (torsion K) a = ⊥ := by + refine (Subgroup.eq_bot_iff_forall _).mpr fun ζ hζ ↦ ?_ + rwa [MulAction.mem_stabilizer_iff, Subtype.ext_iff, integralPoint_torsionSMul_smul_coe, + unitSMul_smul, ← mixedEmbedding_preimageOfIntegralPoint, ← map_mul, + (mixedEmbedding_injective K).eq_iff, ← map_mul, ← RingOfIntegers.ext_iff, mul_eq_right₀, + Units.val_eq_one, OneMemClass.coe_eq_one] at hζ + exact nonZeroDivisors.coe_ne_zero _ + +open Submodule Ideal + +variable (K) in +/-- The equivalence between `integralPoint K` and the product of the set of nonzero principal +ideals of `K` and the torsion of `K`. -/ +def integralPointEquiv : + integralPoint K ≃ {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.val} × torsion K := + (MulAction.selfEquivSigmaOrbitsQuotientStabilizer (torsion K) (integralPoint K)).trans + ((Equiv.sigmaEquivProdOfEquiv (by + intro _ + simp_rw [integralPoint_torsionSMul_stabilizer] + exact QuotientGroup.quotientBot.toEquiv)).trans + (Equiv.prodCongrLeft (fun _ ↦ (integralPointQuotEquivAssociates K).trans + (Ideal.associatesNonZeroDivisorsEquivIsPrincipal (𝓞 K))))) + +@[simp] +theorem integralPointEquiv_apply_fst (a : integralPoint K) : + ((integralPointEquiv K a).1 : Ideal (𝓞 K)) = span {(preimageOfIntegralPoint a : 𝓞 K)} := rfl + +variable (K) in +/-- For an integer `n`, The equivalence between the `integralPoint K` of norm `n` and the product +of the set of nonzero principal ideals of `K` of norm `n` and the torsion of `K`. -/ +def integralPointEquivNorm (n : ℕ) : + {a : integralPoint K // intNorm a = n} ≃ + {I : (Ideal (𝓞 K))⁰ // IsPrincipal (I : Ideal (𝓞 K)) ∧ + absNorm (I : Ideal (𝓞 K)) = n} × (torsion K) := + calc {a // intNorm a = n} + ≃ {I : {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.1} × torsion K // + absNorm (I.1 : Ideal (𝓞 K)) = n} := + (Equiv.subtypeEquiv (integralPointEquiv K) fun _ ↦ by simp [intNorm, absNorm_span_singleton]) + _ ≃ {I : {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.1} // absNorm (I.1 : Ideal (𝓞 K)) = n} × + torsion K := + Equiv.prodSubtypeFstEquivSubtypeProd (p := fun I : {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.1} ↦ + absNorm (I : Ideal (𝓞 K)) = n) + _ ≃ {I : (Ideal (𝓞 K))⁰ // IsPrincipal (I : Ideal (𝓞 K)) ∧ + absNorm (I : Ideal (𝓞 K)) = n} × (torsion K) := + Equiv.prodCongrLeft fun _ ↦ (Equiv.subtypeSubtypeEquivSubtypeInter + (fun I : (Ideal (𝓞 K))⁰ ↦ IsPrincipal I.1) (fun I ↦ absNorm I.1 = n)) + +@[simp] +theorem integralPointEquivNorm_apply_fst {n : ℕ} {a : integralPoint K} (ha : intNorm a = n) : + ((integralPointEquivNorm K n ⟨a, ha⟩).1 : Ideal (𝓞 K)) = + span {(preimageOfIntegralPoint a : 𝓞 K)} := by + simp_rw [integralPointEquivNorm, Equiv.prodSubtypeFstEquivSubtypeProd, Equiv.instTrans_trans, + Equiv.prodCongrLeft, Equiv.trans_apply, Equiv.subtypeEquiv_apply, Equiv.coe_fn_mk, + Equiv.subtypeSubtypeEquivSubtypeInter_apply_coe, integralPointEquiv_apply_fst] + +variable (K) + +/-- For `n` positive, the number of principal ideals in `𝓞 K` of norm `n` multiplied by the order +of the torsion of `K` is equal to the number of `integralPoint K` of norm `n`. -/ +theorem card_isPrincipal_norm_eq_mul_torsion (n : ℕ) : + Nat.card {I : (Ideal (𝓞 K))⁰ | IsPrincipal (I : Ideal (𝓞 K)) ∧ + absNorm (I : Ideal (𝓞 K)) = n} * torsionOrder K = + Nat.card {a : integralPoint K | intNorm a = n} := by + rw [torsionOrder, PNat.mk_coe, ← Nat.card_eq_fintype_card, ← Nat.card_prod] + exact Nat.card_congr (integralPointEquivNorm K n).symm + +/-- For `s : ℝ`, the number of principal nonzero ideals in `𝓞 K` of norm `≤ s` multiplied by the +order of the torsion of `K` is equal to the number of `integralPoint K` of norm `≤ s`. -/ +theorem card_isPrincipal_norm_le_mul_torsion (s : ℝ) : + Nat.card {I : (Ideal (𝓞 K))⁰ | IsPrincipal (I : Ideal (𝓞 K)) ∧ + absNorm (I : Ideal (𝓞 K)) ≤ s} * torsionOrder K = + Nat.card {a : integralPoint K | intNorm a ≤ s} := by + obtain hs | hs := le_or_gt 0 s + · simp_rw [← Nat.le_floor_iff hs] + rw [torsionOrder, PNat.mk_coe, ← Nat.card_eq_fintype_card, ← Nat.card_prod] + refine Nat.card_congr <| @Equiv.ofFiberEquiv _ (γ := Finset.Iic _) _ + (fun I ↦ ⟨absNorm (I.1 : Ideal (𝓞 K)), Finset.mem_Iic.mpr I.1.2.2⟩) + (fun a ↦ ⟨intNorm a.1, Finset.mem_Iic.mpr a.2⟩) fun ⟨i, hi⟩ ↦ ?_ + simp_rw [Subtype.mk.injEq] + calc + _ ≃ {I : {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.1 ∧ absNorm I.1 ≤ _} // absNorm I.1.1 = i} + × torsion K := Equiv.prodSubtypeFstEquivSubtypeProd + _ ≃ {I : (Ideal (𝓞 K))⁰ // (IsPrincipal I.1 ∧ absNorm I.1 ≤ _) ∧ absNorm I.1 = i} + × torsion K := + Equiv.prodCongrLeft fun _ ↦ (Equiv.subtypeSubtypeEquivSubtypeInter + (p := fun I : (Ideal (𝓞 K))⁰ ↦ IsPrincipal I.1 ∧ absNorm I.1 ≤ _) + (q := fun I ↦ absNorm I.1 = i)) + _ ≃ {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.1 ∧ absNorm I.1 = i ∧ absNorm I.1 ≤ _} + × torsion K := + Equiv.prodCongrLeft fun _ ↦ (Equiv.subtypeEquivRight fun _ ↦ by aesop) + _ ≃ {I : (Ideal (𝓞 K))⁰ // IsPrincipal I.1 ∧ absNorm I.1 = i} × torsion K := + Equiv.prodCongrLeft fun _ ↦ (Equiv.subtypeEquivRight fun _ ↦ by + rw [and_iff_left_of_imp (a := absNorm _ = _) fun h ↦ Finset.mem_Iic.mp (h ▸ hi)]) + _ ≃ {a : integralPoint K // intNorm a = i} := (integralPointEquivNorm K i).symm + _ ≃ {a : {a : integralPoint K // intNorm a ≤ _} // intNorm a.1 = i} := + (Equiv.subtypeSubtypeEquivSubtype fun h ↦ Finset.mem_Iic.mp (h ▸ hi)).symm + · simp_rw [lt_iff_not_le.mp (lt_of_lt_of_le hs (Nat.cast_nonneg _)), and_false, Set.setOf_false, + Nat.card_eq_fintype_card, Fintype.card_ofIsEmpty, zero_mul] + end fundamentalCone end From b978dc4ce9ac8b9d3b46b5fe1c22dc11a010dd8b Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Mon, 23 Sep 2024 17:07:28 +0000 Subject: [PATCH 097/170] =?UTF-8?q?doc:=20fix=20a=20typo=20in=20=C3=A9tale?= =?UTF-8?q?=20algebra=20definition=20=20(#17056)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Antoine Leudière --- Mathlib/RingTheory/Etale/Basic.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/RingTheory/Etale/Basic.lean b/Mathlib/RingTheory/Etale/Basic.lean index 0a5d43bc3a05a..171f57f41c31c 100644 --- a/Mathlib/RingTheory/Etale/Basic.lean +++ b/Mathlib/RingTheory/Etale/Basic.lean @@ -11,7 +11,7 @@ import Mathlib.RingTheory.Unramified.Basic # Etale morphisms -An `R`-algebra `A` is formally étale if for every `R`-algebra, +An `R`-algebra `A` is formally étale if for every `R`-algebra `B`, every square-zero ideal `I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists exactly one lift `A →ₐ[R] B`. It is étale if it is formally étale and of finite presentation. From 8192b1aeed705058e2c7369599897104813e0ba0 Mon Sep 17 00:00:00 2001 From: Christopher Hoskin Date: Mon, 23 Sep 2024 18:06:28 +0000 Subject: [PATCH 098/170] feature(Analysis/Normed/Module/Dual): Add a few polar lemmas (#16426) Adds a few trivial polar lemmas. CC: @urkud Co-authored-by: Christopher Hoskin --- Mathlib/Analysis/LocallyConvex/Polar.lean | 4 ++++ Mathlib/Analysis/Normed/Module/Dual.lean | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Mathlib/Analysis/LocallyConvex/Polar.lean b/Mathlib/Analysis/LocallyConvex/Polar.lean index c640565fce415..dba80d95bd857 100644 --- a/Mathlib/Analysis/LocallyConvex/Polar.lean +++ b/Mathlib/Analysis/LocallyConvex/Polar.lean @@ -64,6 +64,10 @@ theorem polar_mem (s : Set E) (y : F) (hy : y ∈ B.polar s) : ∀ x ∈ s, ‖B theorem zero_mem_polar (s : Set E) : (0 : F) ∈ B.polar s := fun _ _ => by simp only [map_zero, norm_zero, zero_le_one] +theorem polar_nonempty (s : Set E) : Set.Nonempty (B.polar s) := by + use 0 + exact zero_mem_polar B s + theorem polar_eq_iInter {s : Set E} : B.polar s = ⋂ x ∈ s, { y : F | ‖B x y‖ ≤ 1 } := by ext simp only [polar_mem_iff, Set.mem_iInter, Set.mem_setOf_eq] diff --git a/Mathlib/Analysis/Normed/Module/Dual.lean b/Mathlib/Analysis/Normed/Module/Dual.lean index 91bfbe1dc1f82..2892b13b82927 100644 --- a/Mathlib/Analysis/Normed/Module/Dual.lean +++ b/Mathlib/Analysis/Normed/Module/Dual.lean @@ -159,6 +159,13 @@ variable {E : Type*} [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] theorem mem_polar_iff {x' : Dual 𝕜 E} (s : Set E) : x' ∈ polar 𝕜 s ↔ ∀ z ∈ s, ‖x' z‖ ≤ 1 := Iff.rfl +@[simp] +theorem zero_mem_polar (s : Set E) : (0 : Dual 𝕜 E) ∈ polar 𝕜 s := + LinearMap.zero_mem_polar _ s + +theorem polar_nonempty (s : Set E) : Set.Nonempty (polar 𝕜 s) := + LinearMap.polar_nonempty _ _ + @[simp] theorem polar_univ : polar 𝕜 (univ : Set E) = {(0 : Dual 𝕜 E)} := (dualPairing 𝕜 E).flip.polar_univ @@ -256,6 +263,10 @@ theorem isBounded_polar_of_mem_nhds_zero {s : Set E} (s_nhd : s ∈ 𝓝 (0 : E) (((dualPairing 𝕜 E).flip.polar_antitone r_ball).trans <| polar_ball_subset_closedBall_div ha r_pos) +@[simp] +theorem polar_empty : polar 𝕜 (∅ : Set E) = Set.univ := + LinearMap.polar_empty _ + @[simp] theorem polar_singleton {a : E} : polar 𝕜 {a} = { x | ‖x a‖ ≤ 1 } := by simp only [polar, LinearMap.polar_singleton, LinearMap.flip_apply, dualPairing_apply] @@ -263,6 +274,9 @@ theorem polar_singleton {a : E} : polar 𝕜 {a} = { x | ‖x a‖ ≤ 1 } := by theorem mem_polar_singleton {a : E} (y : Dual 𝕜 E) : y ∈ polar 𝕜 {a} ↔ ‖y a‖ ≤ 1 := by simp only [polar_singleton, mem_setOf_eq] +theorem polar_zero : polar 𝕜 ({0} : Set E) = Set.univ := + LinearMap.polar_zero _ + theorem sInter_polar_eq_closedBall {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] {r : ℝ} (hr : 0 < r) : ⋂₀ (polar 𝕜 '' { F | F.Finite ∧ F ⊆ closedBall (0 : E) r⁻¹ }) = closedBall 0 r := by From 5b806f5c252ba448ec8c029cd50a2af7ae14c56b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 23 Sep 2024 18:16:12 +0000 Subject: [PATCH 099/170] refactor: Unsimp `div_pow`/`div_zpow` (#17019) ... and additive versions. These lemmas are not affine (`n` appears twice on the RHS and only once on the LHS). Also note that `mul_pow` and `mul_zpow` are analogous but not simp. From LeanAPAP --- Mathlib/Algebra/Group/Basic.lean | 6 ++++-- Mathlib/Analysis/Analytic/Basic.lean | 2 +- Mathlib/Analysis/SpecificLimits/Normed.lean | 2 +- Mathlib/Data/Real/GoldenRatio.lean | 6 +++--- Mathlib/FieldTheory/Differential/Basic.lean | 2 +- Mathlib/LinearAlgebra/RootSystem/Defs.lean | 2 +- Mathlib/Topology/Algebra/Field.lean | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Mathlib/Algebra/Group/Basic.lean b/Mathlib/Algebra/Group/Basic.lean index 492d4bb387a9d..1fd34ff37fdbc 100644 --- a/Mathlib/Algebra/Group/Basic.lean +++ b/Mathlib/Algebra/Group/Basic.lean @@ -586,14 +586,16 @@ theorem mul_div_mul_comm : a * b / (c * d) = a / c * (b / d) := by simp | (n : ℕ) => by simp_rw [zpow_natCast, mul_pow] | .negSucc n => by simp_rw [zpow_negSucc, ← inv_pow, mul_inv, mul_pow] -@[to_additive (attr := simp) nsmul_sub] +@[to_additive nsmul_sub] lemma div_pow (a b : α) (n : ℕ) : (a / b) ^ n = a ^ n / b ^ n := by simp only [div_eq_mul_inv, mul_pow, inv_pow] -@[to_additive (attr := simp) zsmul_sub] +@[to_additive zsmul_sub] lemma div_zpow (a b : α) (n : ℤ) : (a / b) ^ n = a ^ n / b ^ n := by simp only [div_eq_mul_inv, mul_zpow, inv_zpow] +attribute [field_simps] div_pow div_zpow + end DivisionCommMonoid section Group diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index 995fbba71ec66..1abdcf481ef99 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -874,7 +874,7 @@ theorem HasFPowerSeriesWithinAt.isBigO_sub_partialSum_pow refine isBigO_iff.2 ⟨C * (a / r') ^ n, ?_⟩ replace r'0 : 0 < (r' : ℝ) := mod_cast r'0 filter_upwards [inter_mem_nhdsWithin _ (Metric.ball_mem_nhds (0 : E) r'0)] with y hy - simpa [mul_pow, mul_div_assoc, mul_assoc, div_mul_eq_mul_div] + simpa [mul_pow, mul_div_assoc, mul_assoc, div_mul_eq_mul_div, div_pow] using hp y hy.2 n (by simpa using hy.1) /-- Taylor formula for an analytic function, `IsBigO` version. -/ diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index c25802286eeec..b1303cc470be5 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -212,7 +212,7 @@ theorem isLittleO_pow_const_mul_const_pow_const_pow_of_norm_lt {R : Type*} [Norm have A : (fun n ↦ (n : R) ^ k : ℕ → R) =o[atTop] fun n ↦ (r₂ / ‖r₁‖) ^ n := isLittleO_pow_const_const_pow_of_one_lt k ((one_lt_div h0).2 h) suffices (fun n ↦ r₁ ^ n) =O[atTop] fun n ↦ ‖r₁‖ ^ n by - simpa [div_mul_cancel₀ _ (pow_pos h0 _).ne'] using A.mul_isBigO this + simpa [div_mul_cancel₀ _ (pow_pos h0 _).ne', div_pow] using A.mul_isBigO this exact IsBigO.of_bound 1 (by simpa using eventually_norm_pow_le r₁) theorem tendsto_pow_const_div_const_pow_of_one_lt (k : ℕ) {r : ℝ} (hr : 1 < r) : diff --git a/Mathlib/Data/Real/GoldenRatio.lean b/Mathlib/Data/Real/GoldenRatio.lean index 2fd3574db29a0..7165e37237c30 100644 --- a/Mathlib/Data/Real/GoldenRatio.lean +++ b/Mathlib/Data/Real/GoldenRatio.lean @@ -95,7 +95,7 @@ theorem gold_ne_zero : φ ≠ 0 := theorem one_lt_gold : 1 < φ := by refine lt_of_mul_lt_mul_left ?_ (le_of_lt gold_pos) - simp [← sq, gold_pos, zero_lt_one, - div_pow] -- Porting note: Added `- div_pow` + simp [← sq, gold_pos, zero_lt_one] theorem gold_lt_two : φ < 2 := by calc (1 + sqrt 5) / 2 < (1 + 3) / 2 := by gcongr; rw [sqrt_lt'] <;> norm_num @@ -168,12 +168,12 @@ theorem fib_isSol_fibRec : fibRec.IsSolution (fun x => x.fib : ℕ → α) := by /-- The geometric sequence `fun n ↦ φ^n` is a solution of `fibRec`. -/ theorem geom_gold_isSol_fibRec : fibRec.IsSolution (φ ^ ·) := by rw [fibRec.geom_sol_iff_root_charPoly, fibRec_charPoly_eq] - simp [sub_eq_zero, - div_pow] -- Porting note: Added `- div_pow` + simp [sub_eq_zero] /-- The geometric sequence `fun n ↦ ψ^n` is a solution of `fibRec`. -/ theorem geom_goldConj_isSol_fibRec : fibRec.IsSolution (ψ ^ ·) := by rw [fibRec.geom_sol_iff_root_charPoly, fibRec_charPoly_eq] - simp [sub_eq_zero, - div_pow] -- Porting note: Added `- div_pow` + simp [sub_eq_zero] end Fibrec diff --git a/Mathlib/FieldTheory/Differential/Basic.lean b/Mathlib/FieldTheory/Differential/Basic.lean index 61fe57fe7c197..05c4742401057 100644 --- a/Mathlib/FieldTheory/Differential/Basic.lean +++ b/Mathlib/FieldTheory/Differential/Basic.lean @@ -41,7 +41,7 @@ lemma logDeriv_mul (ha : a ≠ 0) (hb : b ≠ 0) : logDeriv (a * b) = logDeriv a lemma logDeriv_div (ha : a ≠ 0) (hb : b ≠ 0) : logDeriv (a / b) = logDeriv a - logDeriv b := by unfold logDeriv - field_simp [Derivation.leibniz_div] + field_simp [Derivation.leibniz_div, smul_sub] ring @[simp] diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 880ff84e9129d..55112f1e275ed 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -433,7 +433,7 @@ lemma two_nsmul_reflection_eq_of_perm_eq (hij : P.reflection_perm i = P.reflecti 2 • ⇑(P.reflection i) = 2 • P.reflection j := by ext x suffices 2 • P.toLin x (P.coroot i) • P.root i = 2 • P.toLin x (P.coroot j) • P.root j by - simpa [reflection_apply] + simpa [reflection_apply, smul_sub] calc 2 • P.toLin x (P.coroot i) • P.root i = P.toLin x (P.coroot i) • ((2 : R) • P.root i) := ?_ _ = P.toLin x (P.coroot i) • (P.pairing i j • P.root j) := ?_ diff --git a/Mathlib/Topology/Algebra/Field.lean b/Mathlib/Topology/Algebra/Field.lean index 7fc53eb7891e7..712e7a66bee25 100644 --- a/Mathlib/Topology/Algebra/Field.lean +++ b/Mathlib/Topology/Algebra/Field.lean @@ -132,7 +132,7 @@ theorem IsPreconnected.eq_or_eq_neg_of_sq_eq [Field 𝕜] [HasContinuousInv₀ (hsq : EqOn (f ^ 2) (g ^ 2) S) (hg_ne : ∀ {x : α}, x ∈ S → g x ≠ 0) : EqOn f g S ∨ EqOn f (-g) S := by have hsq : EqOn ((f / g) ^ 2) 1 S := fun x hx => by - simpa [div_eq_one_iff_eq (pow_ne_zero _ (hg_ne hx))] using hsq hx + simpa [div_eq_one_iff_eq (pow_ne_zero _ (hg_ne hx)), div_pow] using hsq hx simpa (config := { contextual := true }) [EqOn, div_eq_iff (hg_ne _)] using hS.eq_one_or_eq_neg_one_of_sq_eq (hf.div hg fun z => hg_ne) hsq From c133269946b93e1f1885f99781013a3ed9a51b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 23 Sep 2024 19:41:01 +0000 Subject: [PATCH 100/170] feat(Order/SuccPred/Limit): `IsSuccPrelimit.le_iff_forall_le` (#17026) --- Mathlib/Order/SuccPred/Limit.lean | 42 +++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/Mathlib/Order/SuccPred/Limit.lean b/Mathlib/Order/SuccPred/Limit.lean index dd876c6f2254d..45933dc60feb8 100644 --- a/Mathlib/Order/SuccPred/Limit.lean +++ b/Mathlib/Order/SuccPred/Limit.lean @@ -24,7 +24,7 @@ predicate `Order.IsSuccLimit`. -/ -variable {α : Type*} +variable {α : Type*} {a b : α} namespace Order @@ -62,7 +62,7 @@ end LT section Preorder -variable [Preorder α] {a : α} +variable [Preorder α] /-- A successor limit is a value that isn't minimal and doesn't cover any other. @@ -182,7 +182,7 @@ end Preorder section PartialOrder -variable [PartialOrder α] {a b : α} +variable [PartialOrder α] theorem isSuccLimit_iff [OrderBot α] : IsSuccLimit a ↔ a ≠ ⊥ ∧ IsSuccPrelimit a := by rw [IsSuccLimit, isMin_iff_eq_bot] @@ -289,12 +289,28 @@ end IsSuccArchimedean end PartialOrder +section LinearOrder + +variable [LinearOrder α] + +theorem IsSuccPrelimit.le_iff_forall_le (h : IsSuccPrelimit a) : a ≤ b ↔ ∀ c < a, c ≤ b := by + use fun ha c hc ↦ hc.le.trans ha + intro H + by_contra! ha + exact h b ⟨ha, fun c hb hc ↦ (H c hc).not_lt hb⟩ + +theorem IsSuccPrelimit.lt_iff_exists_lt (h : IsSuccPrelimit b) : a < b ↔ ∃ c < b, a < c := by + rw [← not_iff_not] + simp [h.le_iff_forall_le] + +end LinearOrder + /-! ### Predecessor limits -/ section LT -variable [LT α] {a : α} +variable [LT α] /-- A predecessor pre-limit is a value that isn't covered by any other. @@ -335,7 +351,7 @@ end LT section Preorder -variable [Preorder α] {a : α} +variable [Preorder α] /-- A predecessor limit is a value that isn't maximal and doesn't cover any other. @@ -462,7 +478,7 @@ end Preorder section PartialOrder -variable [PartialOrder α] {a b : α} +variable [PartialOrder α] theorem isPredLimit_iff [OrderTop α] : IsPredLimit a ↔ a ≠ ⊤ ∧ IsPredPrelimit a := by rw [IsPredLimit, isMax_iff_eq_top] @@ -555,12 +571,24 @@ end IsPredArchimedean end PartialOrder +section LinearOrder + +variable [LinearOrder α] + +theorem IsPredPrelimit.le_iff_forall_le (h : IsPredPrelimit a) : b ≤ a ↔ ∀ ⦃c⦄, a < c → b ≤ c := + h.dual.le_iff_forall_le + +theorem IsPredPrelimit.lt_iff_exists_lt (h : IsPredPrelimit b) : b < a ↔ ∃ c, b < c ∧ c < a := + h.dual.lt_iff_exists_lt + +end LinearOrder + end Order /-! ### Induction principles -/ -variable {C : α → Sort*} {b : α} +variable {C : α → Sort*} namespace Order From 0ad1d17972ad2b5664e9c963da4f3212c898016a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 23 Sep 2024 20:26:00 +0000 Subject: [PATCH 101/170] =?UTF-8?q?feat:=20`a=E2=81=BA=20=3D=20b=E2=81=BA?= =?UTF-8?q?=20=E2=88=A7=20a=E2=81=BB=20=3D=20b=E2=81=BB=20=E2=86=94=20a=20?= =?UTF-8?q?=3D=20b`=20(#17061)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Algebra/Order/Group/PosPart.lean | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/Order/Group/PosPart.lean b/Mathlib/Algebra/Order/Group/PosPart.lean index 078e76ef92cb4..b8af733a70b23 100644 --- a/Mathlib/Algebra/Order/Group/PosPart.lean +++ b/Mathlib/Algebra/Order/Group/PosPart.lean @@ -49,7 +49,7 @@ section Lattice variable [Lattice α] section Group -variable [Group α] {a : α} +variable [Group α] {a b : α} /-- The *positive part* of an element `a` in a lattice ordered group is `a ⊔ 1`, denoted `a⁺ᵐ`. -/ @[to_additive @@ -130,6 +130,16 @@ lemma leOnePart_eq_one : a⁻ᵐ = 1 ↔ 1 ≤ a := by simp [leOnePart_eq_one'] @[to_additive (attr := simp)] lemma leOnePart_div_oneLePart (a : α) : a⁻ᵐ / a⁺ᵐ = a⁻¹ := by rw [← inv_div, oneLePart_div_leOnePart] +@[to_additive] +lemma oneLePart_leOnePart_injective : Injective fun a : α ↦ (a⁺ᵐ, a⁻ᵐ) := by + simp only [Injective, Prod.mk.injEq, and_imp] + rintro a b hpos hneg + rw [← oneLePart_div_leOnePart a, ← oneLePart_div_leOnePart b, hpos, hneg] + +@[to_additive] +lemma oneLePart_leOnePart_inj : a⁺ᵐ = b⁺ᵐ ∧ a⁻ᵐ = b⁻ᵐ ↔ a = b := + Prod.mk.inj_iff.symm.trans oneLePart_leOnePart_injective.eq_iff + section covariantmulop variable [CovariantClass α α (swap (· * ·)) (· ≤ ·)] @@ -200,7 +210,7 @@ end CommGroup end Lattice section LinearOrder -variable [LinearOrder α] [Group α] {a : α} +variable [LinearOrder α] [Group α] {a b : α} @[to_additive] lemma oneLePart_eq_ite : a⁺ᵐ = if 1 ≤ a then a else 1 := by rw [oneLePart, ← maxDefault, ← sup_eq_maxDefault]; simp_rw [sup_comm] @@ -212,6 +222,8 @@ variable [LinearOrder α] [Group α] {a : α} lemma oneLePart_of_one_lt_oneLePart (ha : 1 < a⁺ᵐ) : a⁺ᵐ = a := by rw [oneLePart, right_lt_sup, not_le] at ha; exact oneLePart_eq_self.2 ha.le +@[to_additive (attr := simp)] lemma oneLePart_lt : a⁺ᵐ < b ↔ a < b ∧ 1 < b := sup_lt_iff + section covariantmul variable [CovariantClass α α (· * ·) (· ≤ ·)] @@ -221,6 +233,11 @@ variable [CovariantClass α α (· * ·) (· ≤ ·)] @[to_additive (attr := simp) negPart_pos_iff] lemma one_lt_ltOnePart_iff : 1 < a⁻ᵐ ↔ a < 1 := lt_iff_lt_of_le_iff_le <| (one_le_leOnePart _).le_iff_eq.trans leOnePart_eq_one +variable [CovariantClass α α (swap (· * ·)) (· ≤ ·)] + +@[to_additive (attr := simp)] lemma leOnePart_lt : a⁻ᵐ < b ↔ b⁻¹ < a ∧ 1 < b := + sup_lt_iff.trans <| by rw [inv_lt'] + end covariantmul end LinearOrder From 3b44012533a6ff066c683a2a4a4320b7997c27df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Kjos-Hanssen?= Date: Mon, 23 Sep 2024 21:06:06 +0000 Subject: [PATCH 102/170] feat: The computable functions are closed under if-then-else definitions with computable predicates (#17039) As discussed at https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/by.20decide.20implies.20Computable/near/471964724 Co-authored-by: Eric Wieser --- Mathlib/Computability/Halting.lean | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Mathlib/Computability/Halting.lean b/Mathlib/Computability/Halting.lean index 6d113f0675c90..084c5246a26c6 100644 --- a/Mathlib/Computability/Halting.lean +++ b/Mathlib/Computability/Halting.lean @@ -173,6 +173,15 @@ protected theorem not {p : α → Prop} (hp : ComputablePred p) : ComputablePred simp only [Bool.not_eq_true] cases f n <;> rfl⟩ +/-- The computable functions are closed under if-then-else definitions +with computable predicates. -/ +theorem ite {f₁ f₂ : ℕ → ℕ} (hf₁ : Computable f₁) (hf₂ : Computable f₂) + {c : ℕ → Prop} [DecidablePred c] (hc : ComputablePred c) : + Computable fun k ↦ if c k then f₁ k else f₂ k := by + simp_rw [← Bool.cond_decide] + obtain ⟨inst, hc⟩ := hc + convert hc.cond hf₁ hf₂ + theorem to_re {p : α → Prop} (hp : ComputablePred p) : RePred p := by obtain ⟨f, hf, rfl⟩ := computable_iff.1 hp unfold RePred From 26254648033e3129265c71fff5e2d2fe57b7bc04 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Mon, 23 Sep 2024 23:48:48 +0000 Subject: [PATCH 103/170] chore(scripts/create-adaptation-pr): Add automatic mode using zulip-send (#17060) --- scripts/create-adaptation-pr.sh | 114 +++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 9 deletions(-) diff --git a/scripts/create-adaptation-pr.sh b/scripts/create-adaptation-pr.sh index 08db7705144c9..2e7d69f7916d8 100755 --- a/scripts/create-adaptation-pr.sh +++ b/scripts/create-adaptation-pr.sh @@ -14,15 +14,52 @@ set -e # abort whenever a command in the script fails # So please do not delete the following line, or the final two lines of this script. { -if [ $# -ne 2 ]; then +# Default values +AUTO="no" + +# Function to display usage +usage() { echo "Usage: $0 " + echo " or" + echo " $0 --bumpversion= --nightlydate= [--auto=]" echo "BUMPVERSION: The upcoming release that we are targeting, e.g., 'v4.10.0'" echo "NIGHTLYDATE: The date of the nightly toolchain currently used on 'nightly-testing'" + echo "AUTO: Optional flag to specify automatic mode, default is 'no'" exit 1 +} + +# Parse arguments +if [ $# -eq 2 ] && [[ $1 != --* ]] && [[ $2 != --* ]]; then + BUMPVERSION=$1 + NIGHTLYDATE=$2 +elif [ $# -ge 2 ]; then + for arg in "$@"; do + case $arg in + --bumpversion=*) + BUMPVERSION="${arg#*=}" + shift + ;; + --nightlydate=*) + NIGHTLYDATE="${arg#*=}" + shift + ;; + --auto=*) + AUTO="${arg#*=}" + shift + ;; + *) + usage + ;; + esac + done +else + usage fi -BUMPVERSION=$1 # "v4.10.0" -NIGHTLYDATE=$2 # "2024-06-25" +# Validate required arguments +if [ -z "$BUMPVERSION" ] || [ -z "$NIGHTLYDATE" ]; then + usage +fi # Check if 'gh' command is available if ! command -v gh &> /dev/null; then @@ -38,8 +75,13 @@ if [ "$status" != "completed" ]; then gh run list --branch nightly-testing exit 1 else - echo "The latest commit on 'nightly-testing' is still running CI." - read -p "Press enter to continue, or ctrl-C if you'd prefer to wait for CI." + if [ "$AUTO" = "yes" ]; then + echo "Auto mode enabled. Bailing out because the latest commit on 'nightly-testing' is still running CI." + exit 1 + else + echo "The latest commit on 'nightly-testing' is still running CI." + read -p "Press enter to continue, or ctrl-C if you'd prefer to wait for CI." + fi fi fi @@ -79,6 +121,13 @@ if git diff --name-only --diff-filter=U | grep -q .; then fi fi +if git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet HEAD --; then + if [ "$AUTO" = "yes" ]; then + echo "Auto mode enabled. Bailing out due to unresolved conflicts or uncommitted changes." + exit 1 + fi +fi + # Loop until all conflicts are resolved and committed while git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet HEAD --; do echo @@ -111,6 +160,13 @@ if git diff --name-only --diff-filter=U | grep -q .; then git add lean-toolchain lake-manifest.json fi +if git diff --name-only --diff-filter=U | grep -q .; then + if [ "$AUTO" = "yes" ]; then + echo "Auto mode enabled. Bailing out due to unresolved conflicts or uncommitted changes." + exit 1 + fi +fi + # Check if there are more merge conflicts if git diff --name-only --diff-filter=U | grep -q .; then echo @@ -143,8 +199,13 @@ if git diff --name-only bump/$BUMPVERSION bump/nightly-$NIGHTLYDATE | grep -q .; echo "Here is a suggested 'gh' command to do this:" gh_command="gh pr create -t \"$pr_title\" -b '' -B bump/$BUMPVERSION" echo "> $gh_command" - echo "Shall I run this command for you? (y/n)" - read answer + if [ "$AUTO" = "yes" ]; then + echo "Auto mode enabled. Running the command..." + answer="y" + else + echo "Shall I run this command for you? (y/n)" + read answer + fi if [ "$answer" != "${answer#[Yy]}" ]; then gh_output=$(eval $gh_command) # Extract the PR number from the output @@ -152,7 +213,7 @@ if git diff --name-only bump/$BUMPVERSION bump/nightly-$NIGHTLYDATE | grep -q .; fi echo - echo "### [user] post a link to the PR on Zulip" + echo "### [auto/user] post a link to the PR on Zulip" zulip_title="#$pr_number adaptations for nightly-$NIGHTLYDATE" zulip_body="> $pr_title #$pr_number" @@ -161,7 +222,33 @@ if git diff --name-only bump/$BUMPVERSION bump/nightly-$NIGHTLYDATE | grep -q .; echo "Here is a suggested message:" echo "Title: $zulip_title" echo " Body: $zulip_body" - read -p "Press enter to continue" + + if command -v zulip-send >/dev/null 2>&1; then + zulip_command="zulip-send --stream nightly-testing --subject \"$zulip_title\" --message \"$zulip_body\"" + echo "Here is a suggested 'zulip-send' command to do this:" + echo "> $zulip_command" + + if [ "$AUTO" = "yes" ]; then + echo "Auto mode enabled. Running the command..." + answer="y" + else + echo "Shall I run this command for you? (y/n)" + read answer + fi + + if [ "$answer" != "${answer#[Yy]}" ]; then + eval $zulip_command + fi + else + echo "Zulip CLI is not installed. Please install it to send messages automatically." + if [ "$AUTO" = "yes" ]; then + exit 1 + fi + fi + + if [ "$AUTO" != "yes" ]; then + read -p "Press enter to continue" + fi # else, let the user know that no PR is needed else @@ -195,6 +282,15 @@ if git diff --name-only --diff-filter=U | grep -q .; then fi fi +if git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet HEAD --; then + if [ "$AUTO" = "yes" ]; then + echo "Auto mode enabled. Bailing out due to unresolved conflicts or uncommitted changes." + echo "PR has been created, and message posted to Zulip." + echo "Error occured while merging the new branch into 'nightly-testing'." + exit 2 + fi +fi + # Loop until all conflicts are resolved and committed while git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet HEAD --; do echo From 7bfd6ed912e1685db12c0180cf2ff28a8d2e75a4 Mon Sep 17 00:00:00 2001 From: thorimur <68410468+thorimur@users.noreply.github.com> Date: Mon, 23 Sep 2024 23:58:37 +0000 Subject: [PATCH 104/170] chore: stop using 'old-style' `tfae_have` syntax (#11000) Banishes "Mathlib `have`" style syntax for `tfae_have` (but does not officially deprecate it). Since we now have the chance to supply a term after `tfae_have ... :=`, we remove one-line `exact`s where possible, and convert `intro`s and some `rintros` into match alternatives. Most single-line `fun`s are preserved. Co-authored-by: Yury G. Kudryashov --- Mathlib/Algebra/Exact.lean | 22 ++++---- .../Homology/ShortComplex/ExactFunctor.lean | 33 +++++------ Mathlib/Algebra/Order/ToIntervalMod.lean | 12 ++-- Mathlib/Analysis/BoxIntegral/Box/Basic.lean | 11 ++-- Mathlib/Analysis/InnerProductSpace/Basic.lean | 13 ++--- .../Analysis/LocallyConvex/WithSeminorms.lean | 18 +++--- .../NormedSpace/OperatorNorm/NormedSpace.lean | 33 +++++------ Mathlib/Analysis/RCLike/Basic.lean | 10 ++-- Mathlib/Analysis/SpecificLimits/Normed.lean | 31 ++++------ Mathlib/CategoryTheory/Abelian/Exact.lean | 18 ++---- .../Bicategory/Kan/Adjunction.lean | 18 ++---- Mathlib/FieldTheory/Galois.lean | 18 ++---- Mathlib/FieldTheory/KummerExtension.lean | 9 +-- Mathlib/GroupTheory/Nilpotent.lean | 11 ++-- Mathlib/LinearAlgebra/Eigenspace/Zero.lean | 31 +++++----- Mathlib/MeasureTheory/Group/Action.lean | 24 +++----- Mathlib/NumberTheory/FLT/Basic.lean | 15 +++-- Mathlib/Order/CompactlyGenerated/Basic.lean | 12 ++-- Mathlib/Order/Height.lean | 14 ++--- Mathlib/Order/WellFoundedSet.lean | 11 ++-- Mathlib/RingTheory/Bezout.lean | 8 +-- .../DiscreteValuationRing/TFAE.lean | 26 ++++----- .../RingTheory/Flat/EquationalCriterion.lean | 19 +++---- Mathlib/RingTheory/Henselian.lean | 7 +-- .../RingTheory/LocalRing/RingHom/Basic.lean | 21 ++----- Mathlib/RingTheory/Valuation/Basic.lean | 8 +-- .../RingTheory/Valuation/ValuationRing.lean | 8 +-- Mathlib/SetTheory/Ordinal/Topology.lean | 20 +++---- .../Algebra/Group/SubmonoidClosure.lean | 14 ++--- .../Category/CompHaus/EffectiveEpi.lean | 18 +++--- .../Category/Profinite/EffectiveEpi.lean | 18 +++--- .../Category/Stonean/EffectiveEpi.lean | 18 +++--- Mathlib/Topology/Inseparable.lean | 23 +++----- Mathlib/Topology/LocallyClosed.lean | 12 ++-- Mathlib/Topology/LocallyConstant/Basic.lean | 13 ++--- Mathlib/Topology/NoetherianSpace.lean | 13 ++--- Mathlib/Topology/Order/LeftRightNhds.lean | 36 +++++------- Mathlib/Topology/Separation.lean | 56 +++++++++---------- .../UniformSpace/UniformConvergence.lean | 8 +-- 39 files changed, 298 insertions(+), 412 deletions(-) diff --git a/Mathlib/Algebra/Exact.lean b/Mathlib/Algebra/Exact.lean index 8a023b47a692f..e3eb8a8116504 100644 --- a/Mathlib/Algebra/Exact.lean +++ b/Mathlib/Algebra/Exact.lean @@ -323,19 +323,17 @@ theorem Exact.split_tfae' (h : Function.Exact f g) : Function.Surjective g ∧ ∃ l, l ∘ₗ f = LinearMap.id, ∃ e : N ≃ₗ[R] M × P, f = e.symm ∘ₗ LinearMap.inl R M P ∧ g = LinearMap.snd R M P ∘ₗ e] := by tfae_have 1 → 3 - · rintro ⟨hf, l, hl⟩ - exact ⟨_, (h.splitSurjectiveEquiv hf ⟨l, hl⟩).2⟩ + | ⟨hf, l, hl⟩ => ⟨_, (h.splitSurjectiveEquiv hf ⟨l, hl⟩).2⟩ tfae_have 2 → 3 - · rintro ⟨hg, l, hl⟩ - exact ⟨_, (h.splitInjectiveEquiv hg ⟨l, hl⟩).2⟩ + | ⟨hg, l, hl⟩ => ⟨_, (h.splitInjectiveEquiv hg ⟨l, hl⟩).2⟩ tfae_have 3 → 1 - · rintro ⟨e, e₁, e₂⟩ + | ⟨e, e₁, e₂⟩ => by have : Function.Injective f := e₁ ▸ e.symm.injective.comp LinearMap.inl_injective - refine ⟨this, ⟨_, ((h.splitSurjectiveEquiv this).symm ⟨e, e₁, e₂⟩).2⟩⟩ + exact ⟨this, ⟨_, ((h.splitSurjectiveEquiv this).symm ⟨e, e₁, e₂⟩).2⟩⟩ tfae_have 3 → 2 - · rintro ⟨e, e₁, e₂⟩ + | ⟨e, e₁, e₂⟩ => by have : Function.Surjective g := e₂ ▸ Prod.snd_surjective.comp e.surjective - refine ⟨this, ⟨_, ((h.splitInjectiveEquiv this).symm ⟨e, e₁, e₂⟩).2⟩⟩ + exact ⟨this, ⟨_, ((h.splitInjectiveEquiv this).symm ⟨e, e₁, e₂⟩).2⟩⟩ tfae_finish /-- Equivalent characterizations of split exact sequences. Also known as the **Splitting lemma**. -/ @@ -347,10 +345,10 @@ theorem Exact.split_tfae ∃ l, g ∘ₗ l = LinearMap.id, ∃ l, l ∘ₗ f = LinearMap.id, ∃ e : N ≃ₗ[R] M × P, f = e.symm ∘ₗ LinearMap.inl R M P ∧ g = LinearMap.snd R M P ∘ₗ e] := by - tfae_have 1 ↔ 3 - · simpa using (h.splitSurjectiveEquiv hf).nonempty_congr - tfae_have 2 ↔ 3 - · simpa using (h.splitInjectiveEquiv hg).nonempty_congr + tfae_have 1 ↔ 3 := by + simpa using (h.splitSurjectiveEquiv hf).nonempty_congr + tfae_have 2 ↔ 3 := by + simpa using (h.splitInjectiveEquiv hg).nonempty_congr tfae_finish end split diff --git a/Mathlib/Algebra/Homology/ShortComplex/ExactFunctor.lean b/Mathlib/Algebra/Homology/ShortComplex/ExactFunctor.lean index 974a1c8685585..d61079ee62930 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ExactFunctor.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ExactFunctor.lean @@ -116,7 +116,7 @@ lemma preservesFiniteLimits_tfae : List.TFAE Nonempty <| PreservesFiniteLimits F ] := by tfae_have 1 → 2 - · rintro hF S ⟨hS, hf⟩ + | hF, S, ⟨hS, hf⟩ => by have := preservesMonomorphisms_of_preserves_shortExact_left F hF refine ⟨?_, inferInstance⟩ let T := ShortComplex.mk S.f (Abelian.coimage.π S.g) (Abelian.comp_coimage_π_eq_zero S.zero) @@ -129,7 +129,7 @@ lemma preservesFiniteLimits_tfae : List.TFAE exact (exact_iff_of_epi_of_isIso_of_mono φ).1 (hF T ⟨(S.exact_iff_exact_coimage_π).1 hS⟩).1 tfae_have 2 → 3 - · intro hF X Y f + | hF, X, Y, f => by refine ⟨preservesLimitOfPreservesLimitCone (kernelIsKernel f) ?_⟩ apply (KernelFork.isLimitMapConeEquiv _ F).2 let S := ShortComplex.mk _ _ (kernel.condition f) @@ -138,13 +138,13 @@ lemma preservesFiniteLimits_tfae : List.TFAE exact hS.1.fIsKernel tfae_have 3 → 4 - · intro hF + | hF => by have := fun X Y (f : X ⟶ Y) ↦ (hF f).some exact ⟨preservesFiniteLimitsOfPreservesKernels F⟩ tfae_have 4 → 1 - · rintro ⟨_⟩ S hS - exact (S.map F).exact_and_mono_f_iff_f_is_kernel |>.2 ⟨KernelFork.mapIsLimit _ hS.fIsKernel F⟩ + | ⟨_⟩, S, hS => + (S.map F).exact_and_mono_f_iff_f_is_kernel |>.2 ⟨KernelFork.mapIsLimit _ hS.fIsKernel F⟩ tfae_finish @@ -175,7 +175,7 @@ lemma preservesFiniteColimits_tfae : List.TFAE Nonempty <| PreservesFiniteColimits F ] := by tfae_have 1 → 2 - · rintro hF S ⟨hS, hf⟩ + | hF, S, ⟨hS, hf⟩ => by have := preservesEpimorphisms_of_preserves_shortExact_right F hF refine ⟨?_, inferInstance⟩ let T := ShortComplex.mk (Abelian.image.ι S.f) S.g (Abelian.image_ι_comp_eq_zero S.zero) @@ -188,7 +188,7 @@ lemma preservesFiniteColimits_tfae : List.TFAE exact (exact_iff_of_epi_of_isIso_of_mono φ).2 (hF T ⟨(S.exact_iff_exact_image_ι).1 hS⟩).1 tfae_have 2 → 3 - · intro hF X Y f + | hF, X, Y, f => by refine ⟨preservesColimitOfPreservesColimitCocone (cokernelIsCokernel f) ?_⟩ apply (CokernelCofork.isColimitMapCoconeEquiv _ F).2 let S := ShortComplex.mk _ _ (cokernel.condition f) @@ -197,14 +197,13 @@ lemma preservesFiniteColimits_tfae : List.TFAE exact hS.1.gIsCokernel tfae_have 3 → 4 - · intro hF + | hF => by have := fun X Y (f : X ⟶ Y) ↦ (hF f).some exact ⟨preservesFiniteColimitsOfPreservesCokernels F⟩ tfae_have 4 → 1 - · rintro ⟨_⟩ S hS - exact (S.map F).exact_and_epi_g_iff_g_is_cokernel |>.2 - ⟨CokernelCofork.mapIsColimit _ hS.gIsCokernel F⟩ + | ⟨_⟩, S, hS => (S.map F).exact_and_epi_g_iff_g_is_cokernel |>.2 + ⟨CokernelCofork.mapIsColimit _ hS.gIsCokernel F⟩ tfae_finish @@ -224,7 +223,7 @@ lemma exact_tfae : List.TFAE Nonempty (PreservesFiniteLimits F) ∧ Nonempty (PreservesFiniteColimits F) ] := by tfae_have 1 → 3 - · intro hF + | hF => by refine ⟨fun {X Y} f ↦ ?_, fun {X Y} f ↦ ?_⟩ · have h := (preservesFiniteLimits_tfae F |>.out 0 2 |>.1 fun S hS ↦ And.intro (hF S hS).exact (hF S hS).mono_f) @@ -234,7 +233,7 @@ lemma exact_tfae : List.TFAE exact h f |>.some tfae_have 2 → 1 - · intro hF S hS + | hF, S, hS => by have : Mono (S.map F).f := exact_iff_mono _ (by simp) |>.1 <| hF (.mk (0 : 0 ⟶ S.X₁) S.f <| by simp) (exact_iff_mono _ (by simp) |>.2 hS.mono_f) have : Epi (S.map F).g := exact_iff_epi _ (by simp) |>.1 <| @@ -242,13 +241,11 @@ lemma exact_tfae : List.TFAE exact ⟨hF S hS.exact⟩ tfae_have 3 → 4 - · rintro ⟨h⟩ - exact ⟨⟨preservesFiniteLimitsOfPreservesHomology F⟩, - ⟨preservesFiniteColimitsOfPreservesHomology F⟩⟩ + | ⟨h⟩ => ⟨⟨preservesFiniteLimitsOfPreservesHomology F⟩, + ⟨preservesFiniteColimitsOfPreservesHomology F⟩⟩ tfae_have 4 → 2 - · rintro ⟨⟨h1⟩, ⟨h2⟩⟩ - exact fun _ h ↦ h.map F + | ⟨⟨h1⟩, ⟨h2⟩⟩, _, h => h.map F tfae_finish diff --git a/Mathlib/Algebra/Order/ToIntervalMod.lean b/Mathlib/Algebra/Order/ToIntervalMod.lean index 686d38e4a5a1b..260764b5fe69c 100644 --- a/Mathlib/Algebra/Order/ToIntervalMod.lean +++ b/Mathlib/Algebra/Order/ToIntervalMod.lean @@ -517,23 +517,23 @@ theorem tfae_modEq : [a ≡ b [PMOD p], ∀ z : ℤ, b - z • p ∉ Set.Ioo a (a + p), toIcoMod hp a b ≠ toIocMod hp a b, toIcoMod hp a b + p = toIocMod hp a b] := by rw [modEq_iff_toIcoMod_eq_left hp] - tfae_have 3 → 2 - · rw [← not_exists, not_imp_not] + tfae_have 3 → 2 := by + rw [← not_exists, not_imp_not] exact fun ⟨i, hi⟩ => ((toIcoMod_eq_iff hp).2 ⟨Set.Ioo_subset_Ico_self hi, i, (sub_add_cancel b _).symm⟩).trans ((toIocMod_eq_iff hp).2 ⟨Set.Ioo_subset_Ioc_self hi, i, (sub_add_cancel b _).symm⟩).symm tfae_have 4 → 3 - · intro h + | h => by rw [← h, Ne, eq_comm, add_right_eq_self] exact hp.ne' tfae_have 1 → 4 - · intro h + | h => by rw [h, eq_comm, toIocMod_eq_iff, Set.right_mem_Ioc] refine ⟨lt_add_of_pos_right a hp, toIcoDiv hp a b - 1, ?_⟩ rw [sub_one_zsmul, add_add_add_comm, add_neg_cancel, add_zero] conv_lhs => rw [← toIcoMod_add_toIcoDiv_zsmul hp a b, h] - tfae_have 2 → 1 - · rw [← not_exists, not_imp_comm] + tfae_have 2 → 1 := by + rw [← not_exists, not_imp_comm] have h' := toIcoMod_mem_Ico hp a b exact fun h => ⟨_, h'.1.lt_of_ne' h, h'.2⟩ tfae_finish diff --git a/Mathlib/Analysis/BoxIntegral/Box/Basic.lean b/Mathlib/Analysis/BoxIntegral/Box/Basic.lean index 91269631ab2c4..551320c2187d8 100644 --- a/Mathlib/Analysis/BoxIntegral/Box/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Box/Basic.lean @@ -140,15 +140,12 @@ theorem le_def : I ≤ J ↔ ∀ x ∈ I, x ∈ J := Iff.rfl theorem le_TFAE : List.TFAE [I ≤ J, (I : Set (ι → ℝ)) ⊆ J, Icc I.lower I.upper ⊆ Icc J.lower J.upper, J.lower ≤ I.lower ∧ I.upper ≤ J.upper] := by - tfae_have 1 ↔ 2 - · exact Iff.rfl + tfae_have 1 ↔ 2 := Iff.rfl tfae_have 2 → 3 - · intro h - simpa [coe_eq_pi, closure_pi_set, lower_ne_upper] using closure_mono h - tfae_have 3 ↔ 4 - · exact Icc_subset_Icc_iff I.lower_le_upper + | h => by simpa [coe_eq_pi, closure_pi_set, lower_ne_upper] using closure_mono h + tfae_have 3 ↔ 4 := Icc_subset_Icc_iff I.lower_le_upper tfae_have 4 → 2 - · exact fun h x hx i ↦ Ioc_subset_Ioc (h.1 i) (h.2 i) (hx i) + | h, x, hx, i => Ioc_subset_Ioc (h.1 i) (h.2 i) (hx i) tfae_finish variable {I J} diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index 2e4adbdbee16f..aff60c1cd6250 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -1671,8 +1671,8 @@ theorem norm_inner_eq_norm_tfae (x y : E) : x = 0 ∨ y = (⟪x, y⟫ / ⟪x, x⟫) • x, x = 0 ∨ ∃ r : 𝕜, y = r • x, x = 0 ∨ y ∈ 𝕜 ∙ x] := by - tfae_have 1 → 2 - · refine fun h => or_iff_not_imp_left.2 fun hx₀ => ?_ + tfae_have 1 → 2 := by + refine fun h => or_iff_not_imp_left.2 fun hx₀ => ?_ have : ‖x‖ ^ 2 ≠ 0 := pow_ne_zero _ (norm_ne_zero_iff.2 hx₀) rw [← sq_eq_sq, mul_pow, ← mul_right_inj' this, eq_comm, ← sub_eq_zero, ← mul_sub] at h <;> try positivity @@ -1682,13 +1682,12 @@ theorem norm_inner_eq_norm_tfae (x y : E) : sub_eq_zero] at h rw [div_eq_inv_mul, mul_smul, h, inv_smul_smul₀] rwa [inner_self_ne_zero] - tfae_have 2 → 3 - · exact fun h => h.imp_right fun h' => ⟨_, h'⟩ - tfae_have 3 → 1 - · rintro (rfl | ⟨r, rfl⟩) <;> + tfae_have 2 → 3 := fun h => h.imp_right fun h' => ⟨_, h'⟩ + tfae_have 3 → 1 := by + rintro (rfl | ⟨r, rfl⟩) <;> simp [inner_smul_right, norm_smul, inner_self_eq_norm_sq_to_K, inner_self_eq_norm_mul_norm, sq, mul_left_comm] - tfae_have 3 ↔ 4; · simp only [Submodule.mem_span_singleton, eq_comm] + tfae_have 3 ↔ 4 := by simp only [Submodule.mem_span_singleton, eq_comm] tfae_finish /-- If the inner product of two vectors is equal to the product of their norms, then the two vectors diff --git a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean index c562e61f2eae3..ae6a4a37290bc 100644 --- a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean +++ b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean @@ -623,14 +623,11 @@ protected theorem _root_.WithSeminorms.equicontinuous_TFAE {κ : Type*} clear u hu hq -- Now we can prove the equivalence in this setting simp only [List.map] - tfae_have 1 → 3 - · exact uniformEquicontinuous_of_equicontinuousAt_zero f - tfae_have 3 → 2 - · exact UniformEquicontinuous.equicontinuous - tfae_have 2 → 1 - · exact fun H ↦ H 0 + tfae_have 1 → 3 := uniformEquicontinuous_of_equicontinuousAt_zero f + tfae_have 3 → 2 := UniformEquicontinuous.equicontinuous + tfae_have 2 → 1 := fun H ↦ H 0 tfae_have 3 → 5 - · intro H + | H => by have : ∀ᶠ x in 𝓝 0, ∀ k, q i (f k x) ≤ 1 := by filter_upwards [Metric.equicontinuousAt_iff_right.mp (H.equicontinuous 0) 1 one_pos] with x hx k @@ -642,11 +639,10 @@ protected theorem _root_.WithSeminorms.equicontinuous_TFAE {κ : Type*} refine ⟨bdd, Seminorm.continuous' (r := 1) ?_⟩ filter_upwards [this] with x hx simpa only [closedBall_iSup bdd _ one_pos, mem_iInter, mem_closedBall_zero] using hx - tfae_have 5 → 4 - · exact fun H ↦ ⟨⨆ k, (q i).comp (f k), Seminorm.coe_iSup_eq H.1 ▸ H.2, le_ciSup H.1⟩ + tfae_have 5 → 4 := fun H ↦ ⟨⨆ k, (q i).comp (f k), Seminorm.coe_iSup_eq H.1 ▸ H.2, le_ciSup H.1⟩ tfae_have 4 → 1 -- This would work over any `NormedField` - · intro ⟨p, hp, hfp⟩ - exact Metric.equicontinuousAt_of_continuity_modulus p (map_zero p ▸ hp.tendsto 0) _ <| + | ⟨p, hp, hfp⟩ => + Metric.equicontinuousAt_of_continuity_modulus p (map_zero p ▸ hp.tendsto 0) _ <| Eventually.of_forall fun x k ↦ by simpa using hfp k x tfae_finish diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean index 8530ba797f7ed..85edc3f7a843e 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean @@ -313,33 +313,30 @@ protected theorem NormedSpace.equicontinuous_TFAE : List.TFAE BddAbove (Set.range (‖f ·‖)), (⨆ i, (‖f i‖₊ : ENNReal)) < ⊤ ] := by -- `1 ↔ 2 ↔ 3` follows from `uniformEquicontinuous_of_equicontinuousAt_zero` - tfae_have 1 → 3 - · exact uniformEquicontinuous_of_equicontinuousAt_zero f - tfae_have 3 → 2 - · exact UniformEquicontinuous.equicontinuous - tfae_have 2 → 1 - · exact fun H ↦ H 0 + tfae_have 1 → 3 := uniformEquicontinuous_of_equicontinuousAt_zero f + tfae_have 3 → 2 := UniformEquicontinuous.equicontinuous + tfae_have 2 → 1 := fun H ↦ H 0 -- `4 ↔ 5 ↔ 6 ↔ 7 ↔ 8 ↔ 9` is morally trivial, we just have to use a lot of rewriting -- and `congr` lemmas - tfae_have 4 ↔ 5 - · rw [exists_ge_and_iff_exists] + tfae_have 4 ↔ 5 := by + rw [exists_ge_and_iff_exists] exact fun C₁ C₂ hC ↦ forall₂_imp fun i x ↦ le_trans' <| by gcongr - tfae_have 5 ↔ 7 - · refine exists_congr (fun C ↦ and_congr_right fun hC ↦ forall_congr' fun i ↦ ?_) + tfae_have 5 ↔ 7 := by + refine exists_congr (fun C ↦ and_congr_right fun hC ↦ forall_congr' fun i ↦ ?_) rw [ContinuousLinearMap.opNorm_le_iff hC] - tfae_have 7 ↔ 8 - · simp_rw [bddAbove_iff_exists_ge (0 : ℝ), Set.forall_mem_range] - tfae_have 6 ↔ 8 - · simp_rw [bddAbove_def, Set.forall_mem_range] - tfae_have 8 ↔ 9 - · rw [ENNReal.iSup_coe_lt_top, ← NNReal.bddAbove_coe, ← Set.range_comp] + tfae_have 7 ↔ 8 := by + simp_rw [bddAbove_iff_exists_ge (0 : ℝ), Set.forall_mem_range] + tfae_have 6 ↔ 8 := by + simp_rw [bddAbove_def, Set.forall_mem_range] + tfae_have 8 ↔ 9 := by + rw [ENNReal.iSup_coe_lt_top, ← NNReal.bddAbove_coe, ← Set.range_comp] rfl -- `3 ↔ 4` is the interesting part of the result. It is essentially a combination of -- `WithSeminorms.uniformEquicontinuous_iff_exists_continuous_seminorm` which turns -- equicontinuity into existence of some continuous seminorm and -- `Seminorm.bound_of_continuous_normedSpace` which characterize such seminorms. - tfae_have 3 ↔ 4 - · refine ((norm_withSeminorms 𝕜₂ F).uniformEquicontinuous_iff_exists_continuous_seminorm _).trans + tfae_have 3 ↔ 4 := by + refine ((norm_withSeminorms 𝕜₂ F).uniformEquicontinuous_iff_exists_continuous_seminorm _).trans ?_ rw [forall_const] constructor diff --git a/Mathlib/Analysis/RCLike/Basic.lean b/Mathlib/Analysis/RCLike/Basic.lean index 66edd002bd1e6..869aa9fe0a463 100644 --- a/Mathlib/Analysis/RCLike/Basic.lean +++ b/Mathlib/Analysis/RCLike/Basic.lean @@ -317,16 +317,14 @@ open List in /-- There are several equivalent ways to say that a number `z` is in fact a real number. -/ theorem is_real_TFAE (z : K) : TFAE [conj z = z, ∃ r : ℝ, (r : K) = z, ↑(re z) = z, im z = 0] := by tfae_have 1 → 4 - · intro h + | h => by rw [← @ofReal_inj K, im_eq_conj_sub, h, sub_self, mul_zero, zero_div, ofReal_zero] tfae_have 4 → 3 - · intro h + | h => by conv_rhs => rw [← re_add_im z, h, ofReal_zero, zero_mul, add_zero] - tfae_have 3 → 2 - · exact fun h => ⟨_, h⟩ - tfae_have 2 → 1 - · exact fun ⟨r, hr⟩ => hr ▸ conj_ofReal _ + tfae_have 3 → 2 := fun h => ⟨_, h⟩ + tfae_have 2 → 1 := fun ⟨r, hr⟩ => hr ▸ conj_ofReal _ tfae_finish theorem conj_eq_iff_real {z : K} : conj z = z ↔ ∃ r : ℝ, z = (r : K) := diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index b1303cc470be5..d15e75afada5e 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -130,29 +130,24 @@ theorem TFAE_exists_lt_isLittleO_pow (f : ℕ → ℝ) (R : ℝ) : fun x hx ↦ ⟨(neg_lt_zero.2 (hx.1.trans_lt hx.2)).trans_le hx.1, hx.2⟩ have B : Ioo 0 R ⊆ Ioo (-R) R := Subset.trans Ioo_subset_Ico_self A -- First we prove that 1-4 are equivalent using 2 → 3 → 4, 1 → 3, and 2 → 1 - tfae_have 1 → 3 - · exact fun ⟨a, ha, H⟩ ↦ ⟨a, ha, H.isBigO⟩ - tfae_have 2 → 1 - · exact fun ⟨a, ha, H⟩ ↦ ⟨a, B ha, H⟩ + tfae_have 1 → 3 := fun ⟨a, ha, H⟩ ↦ ⟨a, ha, H.isBigO⟩ + tfae_have 2 → 1 := fun ⟨a, ha, H⟩ ↦ ⟨a, B ha, H⟩ tfae_have 3 → 2 - · rintro ⟨a, ha, H⟩ + | ⟨a, ha, H⟩ => by rcases exists_between (abs_lt.2 ha) with ⟨b, hab, hbR⟩ exact ⟨b, ⟨(abs_nonneg a).trans_lt hab, hbR⟩, H.trans_isLittleO (isLittleO_pow_pow_of_abs_lt_left (hab.trans_le (le_abs_self b)))⟩ - tfae_have 2 → 4 - · exact fun ⟨a, ha, H⟩ ↦ ⟨a, ha, H.isBigO⟩ - tfae_have 4 → 3 - · exact fun ⟨a, ha, H⟩ ↦ ⟨a, B ha, H⟩ + tfae_have 2 → 4 := fun ⟨a, ha, H⟩ ↦ ⟨a, ha, H.isBigO⟩ + tfae_have 4 → 3 := fun ⟨a, ha, H⟩ ↦ ⟨a, B ha, H⟩ -- Add 5 and 6 using 4 → 6 → 5 → 3 tfae_have 4 → 6 - · rintro ⟨a, ha, H⟩ + | ⟨a, ha, H⟩ => by rcases bound_of_isBigO_nat_atTop H with ⟨C, hC₀, hC⟩ refine ⟨a, ha, C, hC₀, fun n ↦ ?_⟩ simpa only [Real.norm_eq_abs, abs_pow, abs_of_nonneg ha.1.le] using hC (pow_ne_zero n ha.1.ne') - tfae_have 6 → 5 - · exact fun ⟨a, ha, C, H₀, H⟩ ↦ ⟨a, ha.2, C, Or.inl H₀, H⟩ + tfae_have 6 → 5 := fun ⟨a, ha, C, H₀, H⟩ ↦ ⟨a, ha.2, C, Or.inl H₀, H⟩ tfae_have 5 → 3 - · rintro ⟨a, ha, C, h₀, H⟩ + | ⟨a, ha, C, h₀, H⟩ => by rcases sign_cases_of_C_mul_pow_nonneg fun n ↦ (abs_nonneg _).trans (H n) with (rfl | ⟨hC₀, ha₀⟩) · obtain rfl : f = 0 := by ext n @@ -163,19 +158,15 @@ theorem TFAE_exists_lt_isLittleO_pow (f : ℕ → ℝ) (R : ℝ) : isBigO_of_le' _ fun n ↦ (H n).trans <| mul_le_mul_of_nonneg_left (le_abs_self _) hC₀.le⟩ -- Add 7 and 8 using 2 → 8 → 7 → 3 tfae_have 2 → 8 - · rintro ⟨a, ha, H⟩ + | ⟨a, ha, H⟩ => by refine ⟨a, ha, (H.def zero_lt_one).mono fun n hn ↦ ?_⟩ rwa [Real.norm_eq_abs, Real.norm_eq_abs, one_mul, abs_pow, abs_of_pos ha.1] at hn - tfae_have 8 → 7 - · exact fun ⟨a, ha, H⟩ ↦ ⟨a, ha.2, H⟩ + tfae_have 8 → 7 := fun ⟨a, ha, H⟩ ↦ ⟨a, ha.2, H⟩ tfae_have 7 → 3 - · rintro ⟨a, ha, H⟩ + | ⟨a, ha, H⟩ => by have : 0 ≤ a := nonneg_of_eventually_pow_nonneg (H.mono fun n ↦ (abs_nonneg _).trans) refine ⟨a, A ⟨this, ha⟩, IsBigO.of_bound 1 ?_⟩ simpa only [Real.norm_eq_abs, one_mul, abs_pow, abs_of_nonneg this] - -- Porting note: used to work without explicitly having 6 → 7 - tfae_have 6 → 7 - · exact fun h ↦ tfae_8_to_7 <| tfae_2_to_8 <| tfae_3_to_2 <| tfae_5_to_3 <| tfae_6_to_5 h tfae_finish /-- For any natural `k` and a real `r > 1` we have `n ^ k = o(r ^ n)` as `n → ∞`. -/ diff --git a/Mathlib/CategoryTheory/Abelian/Exact.lean b/Mathlib/CategoryTheory/Abelian/Exact.lean index 85352b81dbb61..04967ba6b7f80 100644 --- a/Mathlib/CategoryTheory/Abelian/Exact.lean +++ b/Mathlib/CategoryTheory/Abelian/Exact.lean @@ -169,25 +169,19 @@ section open List in theorem Abelian.tfae_mono {X Y : C} (f : X ⟶ Y) (Z : C) : TFAE [Mono f, kernel.ι f = 0, (ShortComplex.mk (0 : Z ⟶ X) f zero_comp).Exact] := by - tfae_have 2 → 1 - · exact mono_of_kernel_ι_eq_zero _ + tfae_have 2 → 1 := mono_of_kernel_ι_eq_zero _ tfae_have 1 → 2 - · intro - rw [← cancel_mono f, kernel.condition, zero_comp] - tfae_have 3 ↔ 1 - · exact ShortComplex.exact_iff_mono _ (by simp) + | _ => by rw [← cancel_mono f, kernel.condition, zero_comp] + tfae_have 3 ↔ 1 := ShortComplex.exact_iff_mono _ (by simp) tfae_finish open List in theorem Abelian.tfae_epi {X Y : C} (f : X ⟶ Y) (Z : C ) : TFAE [Epi f, cokernel.π f = 0, (ShortComplex.mk f (0 : Y ⟶ Z) comp_zero).Exact] := by - tfae_have 2 → 1 - · exact epi_of_cokernel_π_eq_zero _ + tfae_have 2 → 1 := epi_of_cokernel_π_eq_zero _ tfae_have 1 → 2 - · intro - rw [← cancel_epi f, cokernel.condition, comp_zero] - tfae_have 3 ↔ 1 - · exact ShortComplex.exact_iff_epi _ (by simp) + | _ => by rw [← cancel_epi f, cokernel.condition, comp_zero] + tfae_have 3 ↔ 1 := ShortComplex.exact_iff_epi _ (by simp) tfae_finish end diff --git a/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean b/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean index d4ec2116851e0..ac3e11be6fb37 100644 --- a/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean +++ b/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean @@ -106,14 +106,11 @@ theorem isLeftAdjoint_TFAE (f : a ⟶ b) : HasAbsLeftKanExtension f (𝟙 a), ∃ _ : HasLeftKanExtension f (𝟙 a), Lan.CommuteWith f (𝟙 a) f] := by tfae_have 1 → 2 - · intro h - exact IsAbsKan.hasAbsLeftKanExtension (Adjunction.ofIsLeftAdjoint f).isAbsoluteLeftKan + | h => IsAbsKan.hasAbsLeftKanExtension (Adjunction.ofIsLeftAdjoint f).isAbsoluteLeftKan tfae_have 2 → 3 - · intro h - exact ⟨inferInstance, inferInstance⟩ + | h => ⟨inferInstance, inferInstance⟩ tfae_have 3 → 1 - · intro ⟨h, h'⟩ - exact .mk <| (lanIsKan f (𝟙 a)).adjunction <| Lan.CommuteWith.isKan f (𝟙 a) f + | ⟨h, h'⟩ => .mk <| (lanIsKan f (𝟙 a)).adjunction <| Lan.CommuteWith.isKan f (𝟙 a) f tfae_finish end LeftExtension @@ -188,14 +185,11 @@ theorem isRightAdjoint_TFAE (u : b ⟶ a) : HasAbsLeftKanLift u (𝟙 a), ∃ _ : HasLeftKanLift u (𝟙 a), LanLift.CommuteWith u (𝟙 a) u] := by tfae_have 1 → 2 - · intro h - exact IsAbsKan.hasAbsLeftKanLift (Adjunction.ofIsRightAdjoint u).isAbsoluteLeftKanLift + | h => IsAbsKan.hasAbsLeftKanLift (Adjunction.ofIsRightAdjoint u).isAbsoluteLeftKanLift tfae_have 2 → 3 - · intro h - exact ⟨inferInstance, inferInstance⟩ + | h => ⟨inferInstance, inferInstance⟩ tfae_have 3 → 1 - · intro ⟨h, h'⟩ - exact .mk <| (lanLiftIsKan u (𝟙 a)).adjunction <| LanLift.CommuteWith.isKan u (𝟙 a) u + | ⟨h, h'⟩ => .mk <| (lanLiftIsKan u (𝟙 a)).adjunction <| LanLift.CommuteWith.isKan u (𝟙 a) u tfae_finish end LeftLift diff --git a/Mathlib/FieldTheory/Galois.lean b/Mathlib/FieldTheory/Galois.lean index 259a8533aa662..868454440fa9b 100644 --- a/Mathlib/FieldTheory/Galois.lean +++ b/Mathlib/FieldTheory/Galois.lean @@ -391,18 +391,12 @@ theorem tfae [FiniteDimensional F E] : List.TFAE [ IntermediateField.fixedField (⊤ : Subgroup (E ≃ₐ[F] E)) = ⊥, Fintype.card (E ≃ₐ[F] E) = finrank F E, ∃ p : F[X], p.Separable ∧ p.IsSplittingField F E] := by - tfae_have 1 → 2 - · exact fun h => OrderIso.map_bot (@intermediateFieldEquivSubgroup F _ E _ _ _ h).symm - tfae_have 1 → 3 - · intro; exact card_aut_eq_finrank F E - tfae_have 1 → 4 - · intro; exact is_separable_splitting_field F E - tfae_have 2 → 1 - · exact of_fixedField_eq_bot F E - tfae_have 3 → 1 - · exact of_card_aut_eq_finrank F E - tfae_have 4 → 1 - · rintro ⟨h, hp1, _⟩; exact of_separable_splitting_field hp1 + tfae_have 1 → 2 := fun h ↦ OrderIso.map_bot (@intermediateFieldEquivSubgroup F _ E _ _ _ h).symm + tfae_have 1 → 3 := fun _ ↦ card_aut_eq_finrank F E + tfae_have 1 → 4 := fun _ ↦ is_separable_splitting_field F E + tfae_have 2 → 1 := of_fixedField_eq_bot F E + tfae_have 3 → 1 := of_card_aut_eq_finrank F E + tfae_have 4 → 1 := fun ⟨h, hp1, _⟩ ↦ of_separable_splitting_field hp1 tfae_finish end IsGalois diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index 65eb3d88e45c4..18680d5a83dd6 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -638,14 +638,11 @@ lemma isCyclic_tfae (K L) [Field K] [Field L] [Algebra K L] [FiniteDimensional K IsSplittingField K L (X ^ (finrank K L) - C a), ∃ (α : L), α ^ (finrank K L) ∈ Set.range (algebraMap K L) ∧ K⟮α⟯ = ⊤] := by tfae_have 1 → 3 - · intro ⟨inst₁, inst₂⟩ - exact exists_root_adjoin_eq_top_of_isCyclic K L hK + | ⟨inst₁, inst₂⟩ => exists_root_adjoin_eq_top_of_isCyclic K L hK tfae_have 3 → 2 - · intro ⟨α, ⟨a, ha⟩, hα⟩ - exact ⟨a, irreducible_X_pow_sub_C_of_root_adjoin_eq_top ha.symm hα, + | ⟨α, ⟨a, ha⟩, hα⟩ => ⟨a, irreducible_X_pow_sub_C_of_root_adjoin_eq_top ha.symm hα, isSplittingField_X_pow_sub_C_of_root_adjoin_eq_top hK ha.symm hα⟩ tfae_have 2 → 1 - · intro ⟨a, H, inst⟩ - exact ⟨isGalois_of_isSplittingField_X_pow_sub_C hK H L, + | ⟨a, H, inst⟩ => ⟨isGalois_of_isSplittingField_X_pow_sub_C hK H L, isCyclic_of_isSplittingField_X_pow_sub_C hK H L⟩ tfae_finish diff --git a/Mathlib/GroupTheory/Nilpotent.lean b/Mathlib/GroupTheory/Nilpotent.lean index 5e2d9a0bdeadd..90196dde62882 100644 --- a/Mathlib/GroupTheory/Nilpotent.lean +++ b/Mathlib/GroupTheory/Nilpotent.lean @@ -811,16 +811,15 @@ theorem isNilpotent_of_finite_tfae : ∀ (p : ℕ) (_hp : Fact p.Prime) (P : Sylow p G), (↑P : Subgroup G).Normal, Nonempty ((∀ p : (Nat.card G).primeFactors, ∀ P : Sylow p G, (↑P : Subgroup G)) ≃* G)] := by - tfae_have 1 → 2 - · exact @normalizerCondition_of_isNilpotent _ _ + tfae_have 1 → 2 := @normalizerCondition_of_isNilpotent _ _ tfae_have 2 → 3 - · exact fun h H => NormalizerCondition.normal_of_coatom H h + | h, H => NormalizerCondition.normal_of_coatom H h tfae_have 3 → 4 - · intro h p _ P; exact Sylow.normal_of_all_max_subgroups_normal h _ + | h, p, _, P => Sylow.normal_of_all_max_subgroups_normal h _ tfae_have 4 → 5 - · exact fun h => Nonempty.intro (Sylow.directProductOfNormal fun {p hp hP} => h p hp hP) + | h => Nonempty.intro (Sylow.directProductOfNormal fun {p hp hP} => h p hp hP) tfae_have 5 → 1 - · rintro ⟨e⟩; exact isNilpotent_of_product_of_sylow_group e + | ⟨e⟩ => isNilpotent_of_product_of_sylow_group e tfae_finish @[deprecated (since := "2024-06-05")] alias isNilpotent_of_finite_tFAE := isNilpotent_of_finite_tfae diff --git a/Mathlib/LinearAlgebra/Eigenspace/Zero.lean b/Mathlib/LinearAlgebra/Eigenspace/Zero.lean index 53ceb99c2ae29..7830bfb5e4d7f 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Zero.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Zero.lean @@ -52,15 +52,14 @@ lemma charpoly_nilpotent_tfae [IsNoetherian R M] (φ : Module.End R M) : φ.charpoly = X ^ finrank R M, ∀ m : M, ∃ (n : ℕ), (φ ^ n) m = 0, natTrailingDegree φ.charpoly = finrank R M ] := by - tfae_have 1 → 2 - · apply IsNilpotent.charpoly_eq_X_pow_finrank + tfae_have 1 → 2 := IsNilpotent.charpoly_eq_X_pow_finrank _ tfae_have 2 → 3 - · intro h m + | h, m => by use finrank R M suffices φ ^ finrank R M = 0 by simp only [this, LinearMap.zero_apply] simpa only [h, map_pow, aeval_X] using φ.aeval_self_charpoly tfae_have 3 → 1 - · intro h + | h => by obtain ⟨n, hn⟩ := Filter.eventually_atTop.mp <| φ.eventually_iSup_ker_pow_eq use n ext x @@ -68,8 +67,8 @@ lemma charpoly_nilpotent_tfae [IsNoetherian R M] (φ : Module.End R M) : obtain ⟨k, hk⟩ := h x rw [← mem_ker] at hk exact Submodule.mem_iSup_of_mem _ hk - tfae_have 2 ↔ 4 - · rw [← φ.charpoly_natDegree, φ.charpoly_monic.eq_X_pow_iff_natTrailingDegree_eq_natDegree] + tfae_have 2 ↔ 4 := by + rw [← φ.charpoly_natDegree, φ.charpoly_monic.eq_X_pow_iff_natTrailingDegree_eq_natDegree] tfae_finish lemma charpoly_eq_X_pow_iff [IsNoetherian R M] (φ : Module.End R M) : @@ -85,27 +84,25 @@ lemma hasEigenvalue_zero_tfae (φ : Module.End K M) : LinearMap.det φ = 0, ⊥ < ker φ, ∃ (m : M), m ≠ 0 ∧ φ m = 0 ] := by - tfae_have 1 ↔ 2 - · exact Module.End.hasEigenvalue_iff_isRoot - tfae_have 2 → 3 - · obtain ⟨F, hF⟩ := minpoly_dvd_charpoly φ + tfae_have 1 ↔ 2 := Module.End.hasEigenvalue_iff_isRoot + tfae_have 2 → 3 := by + obtain ⟨F, hF⟩ := minpoly_dvd_charpoly φ simp only [IsRoot.def, constantCoeff_apply, coeff_zero_eq_eval_zero, hF, eval_mul] intro h; rw [h, zero_mul] - tfae_have 3 → 4 - · rw [← LinearMap.det_toMatrix (chooseBasis K M), Matrix.det_eq_sign_charpoly_coeff, + tfae_have 3 → 4 := by + rw [← LinearMap.det_toMatrix (chooseBasis K M), Matrix.det_eq_sign_charpoly_coeff, constantCoeff_apply, charpoly] intro h; rw [h, mul_zero] - tfae_have 4 → 5 - · exact bot_lt_ker_of_det_eq_zero - tfae_have 5 → 6 - · contrapose! + tfae_have 4 → 5 := bot_lt_ker_of_det_eq_zero + tfae_have 5 → 6 := by + contrapose! simp only [not_bot_lt_iff, eq_bot_iff] intro h x simp only [mem_ker, Submodule.mem_bot] contrapose! apply h tfae_have 6 → 1 - · rintro ⟨x, h1, h2⟩ + | ⟨x, h1, h2⟩ => by apply Module.End.hasEigenvalue_of_hasEigenvector ⟨_, h1⟩ simpa only [Module.End.eigenspace_zero, mem_ker] using h2 tfae_finish diff --git a/Mathlib/MeasureTheory/Group/Action.lean b/Mathlib/MeasureTheory/Group/Action.lean index 28b06957d5abb..04f432bce67b9 100644 --- a/Mathlib/MeasureTheory/Group/Action.lean +++ b/Mathlib/MeasureTheory/Group/Action.lean @@ -226,23 +226,17 @@ theorem smulInvariantMeasure_tfae : ∀ (c : G) (s), μ (c • s) = μ s, ∀ c : G, Measure.map (c • ·) μ = μ, ∀ c : G, MeasurePreserving (c • ·) μ μ] := by - tfae_have 1 ↔ 2 - · exact ⟨fun h => h.1, fun h => ⟨h⟩⟩ - tfae_have 1 → 6 - · intro h c - exact (measurePreserving_smul c μ).map_eq - tfae_have 6 → 7 - · exact fun H c => ⟨measurable_const_smul c, H c⟩ - tfae_have 7 → 4 - · exact fun H c => (H c).measure_preimage_emb (measurableEmbedding_const_smul c) + tfae_have 1 ↔ 2 := ⟨fun h => h.1, fun h => ⟨h⟩⟩ + tfae_have 1 → 6 := fun h c => (measurePreserving_smul c μ).map_eq + tfae_have 6 → 7 := fun H c => ⟨measurable_const_smul c, H c⟩ + tfae_have 7 → 4 := fun H c => (H c).measure_preimage_emb (measurableEmbedding_const_smul c) tfae_have 4 → 5 - · exact fun H c s => by - rw [← preimage_smul_inv] - apply H - tfae_have 5 → 3 - · exact fun H c s _ => H c s + | H, c, s => by + rw [← preimage_smul_inv] + apply H + tfae_have 5 → 3 := fun H c s _ => H c s tfae_have 3 → 2 - · intro H c s hs + | H, c, s, hs => by rw [preimage_smul] exact H c⁻¹ s hs tfae_finish diff --git a/Mathlib/NumberTheory/FLT/Basic.lean b/Mathlib/NumberTheory/FLT/Basic.lean index 3d9712d21923c..3630dbe1368d9 100644 --- a/Mathlib/NumberTheory/FLT/Basic.lean +++ b/Mathlib/NumberTheory/FLT/Basic.lean @@ -83,7 +83,7 @@ lemma FermatLastTheoremFor.mono (hmn : m ∣ n) (hm : FermatLastTheoremFor m) : lemma fermatLastTheoremWith_nat_int_rat_tfae (n : ℕ) : TFAE [FermatLastTheoremWith ℕ n, FermatLastTheoremWith ℤ n, FermatLastTheoremWith ℚ n] := by tfae_have 1 → 2 - · rintro h a b c ha hb hc habc + | h, a, b, c, ha, hb, hc, habc => by obtain hn | hn := n.even_or_odd · refine h a.natAbs b.natAbs c.natAbs (by positivity) (by positivity) (by positivity) (Int.natCast_inj.1 ?_) @@ -123,7 +123,7 @@ lemma fermatLastTheoremWith_nat_int_rat_tfae (n : ℕ) : push_cast simp only [abs_of_pos, habc, *] tfae_have 2 → 3 - · rintro h a b c ha hb hc habc + | h, a, b, c, ha, hb, hc, habc => by rw [← Rat.num_ne_zero] at ha hb hc refine h (a.num * b.den * c.den) (a.den * b.num * c.den) (a.den * b.den * c.num) (by positivity) (by positivity) (by positivity) ?_ @@ -134,8 +134,7 @@ lemma fermatLastTheoremWith_nat_int_rat_tfae (n : ℕ) : div_self (by positivity : (b.den : ℚ) ≠ 0), div_self (by positivity : (c.den : ℚ) ≠ 0), one_mul, mul_one, Rat.num_div_den, habc] tfae_have 3 → 1 - · rintro h a b c - exact mod_cast h a b c + | h, a, b, c => mod_cast h a b c tfae_finish lemma fermatLastTheoremFor_iff_nat {n : ℕ} : FermatLastTheoremFor n ↔ FermatLastTheoremWith ℕ n := @@ -189,14 +188,14 @@ lemma fermatLastTheoremWith'_iff_fermatLastTheoremWith {α : Type*} [CommSemirin lemma fermatLastTheoremWith'_nat_int_tfae (n : ℕ) : TFAE [FermatLastTheoremFor n, FermatLastTheoremWith' ℕ n, FermatLastTheoremWith' ℤ n] := by - tfae_have 2 ↔ 1 - · apply fermatLastTheoremWith'_iff_fermatLastTheoremWith + tfae_have 2 ↔ 1 := by + apply fermatLastTheoremWith'_iff_fermatLastTheoremWith simp only [Nat.isUnit_iff] intro _ _ _ ha hb hc rw [ha, hb, hc] simp only [one_pow, Nat.reduceAdd, ne_eq, OfNat.ofNat_ne_one, not_false_eq_true] - tfae_have 3 ↔ 1 - · rw [fermatLastTheoremFor_iff_int] + tfae_have 3 ↔ 1 := by + rw [fermatLastTheoremFor_iff_int] apply fermatLastTheoremWith'_iff_fermatLastTheoremWith intro a b c ha hb hc by_cases hn : n = 0 diff --git a/Mathlib/Order/CompactlyGenerated/Basic.lean b/Mathlib/Order/CompactlyGenerated/Basic.lean index 1d5c2b6ad6f39..60620cc7187cf 100644 --- a/Mathlib/Order/CompactlyGenerated/Basic.lean +++ b/Mathlib/Order/CompactlyGenerated/Basic.lean @@ -250,14 +250,10 @@ open List in theorem wellFounded_characterisations : List.TFAE [WellFounded ((· > ·) : α → α → Prop), IsSupFiniteCompact α, IsSupClosedCompact α, ∀ k : α, IsCompactElement k] := by - tfae_have 1 → 2 - · exact WellFounded.isSupFiniteCompact α - tfae_have 2 → 3 - · exact IsSupFiniteCompact.isSupClosedCompact α - tfae_have 3 → 1 - · exact IsSupClosedCompact.wellFounded α - tfae_have 2 ↔ 4 - · exact isSupFiniteCompact_iff_all_elements_compact α + tfae_have 1 → 2 := WellFounded.isSupFiniteCompact α + tfae_have 2 → 3 := IsSupFiniteCompact.isSupClosedCompact α + tfae_have 3 → 1 := IsSupClosedCompact.wellFounded α + tfae_have 2 ↔ 4 := isSupFiniteCompact_iff_all_elements_compact α tfae_finish theorem wellFounded_iff_isSupFiniteCompact : diff --git a/Mathlib/Order/Height.lean b/Mathlib/Order/Height.lean index 531157c49d046..22b9697c5dd05 100644 --- a/Mathlib/Order/Height.lean +++ b/Mathlib/Order/Height.lean @@ -100,9 +100,9 @@ theorem exists_chain_of_le_chainHeight {n : ℕ} (hn : ↑n ≤ s.chainHeight) : theorem le_chainHeight_TFAE (n : ℕ) : TFAE [↑n ≤ s.chainHeight, ∃ l ∈ s.subchain, length l = n, ∃ l ∈ s.subchain, n ≤ length l] := by - tfae_have 1 → 2; · exact s.exists_chain_of_le_chainHeight - tfae_have 2 → 3; · rintro ⟨l, hls, he⟩; exact ⟨l, hls, he.ge⟩ - tfae_have 3 → 1; · rintro ⟨l, hs, hn⟩; exact le_iSup₂_of_le l hs (WithTop.coe_le_coe.2 hn) + tfae_have 1 → 2 := s.exists_chain_of_le_chainHeight + tfae_have 2 → 3 := fun ⟨l, hls, he⟩ ↦ ⟨l, hls, he.ge⟩ + tfae_have 3 → 1 := fun ⟨l, hs, hn⟩ ↦ le_iSup₂_of_le l hs (WithTop.coe_le_coe.2 hn) tfae_finish variable {s t} @@ -169,10 +169,10 @@ theorem chainHeight_add_le_chainHeight_add (s : Set α) (t : Set β) (n m : ℕ) theorem chainHeight_le_chainHeight_TFAE (s : Set α) (t : Set β) : TFAE [s.chainHeight ≤ t.chainHeight, ∀ l ∈ s.subchain, ∃ l' ∈ t.subchain, length l = length l', ∀ l ∈ s.subchain, ∃ l' ∈ t.subchain, length l ≤ length l'] := by - tfae_have 1 ↔ 3 - · convert ← chainHeight_add_le_chainHeight_add s t 0 0 <;> apply add_zero - tfae_have 2 ↔ 3 - · refine forall₂_congr fun l hl ↦ ?_ + tfae_have 1 ↔ 3 := by + convert ← chainHeight_add_le_chainHeight_add s t 0 0 <;> apply add_zero + tfae_have 2 ↔ 3 := by + refine forall₂_congr fun l _ ↦ ?_ simp_rw [← (le_chainHeight_TFAE t l.length).out 1 2, eq_comm] tfae_finish diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index af6576042206c..5c7e684d6af00 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -134,16 +134,15 @@ theorem acc_iff_wellFoundedOn {α} {r : α → α → Prop} {a : α} : TFAE [Acc r a, WellFoundedOn { b | ReflTransGen r b a } r, WellFoundedOn { b | TransGen r b a } r] := by - tfae_have 1 → 2 - · refine fun h => ⟨fun b => InvImage.accessible _ ?_⟩ + tfae_have 1 → 2 := by + refine fun h => ⟨fun b => InvImage.accessible _ ?_⟩ rw [← acc_transGen_iff] at h ⊢ obtain h' | h' := reflTransGen_iff_eq_or_transGen.1 b.2 · rwa [h'] at h · exact h.inv h' - tfae_have 2 → 3 - · exact fun h => h.subset fun _ => TransGen.to_reflTransGen - tfae_have 3 → 1 - · refine fun h => Acc.intro _ (fun b hb => (h.apply ⟨b, .single hb⟩).of_fibration Subtype.val ?_) + tfae_have 2 → 3 := fun h => h.subset fun _ => TransGen.to_reflTransGen + tfae_have 3 → 1 := by + refine fun h => Acc.intro _ (fun b hb => (h.apply ⟨b, .single hb⟩).of_fibration Subtype.val ?_) exact fun ⟨c, hc⟩ d h => ⟨⟨d, .head h hc⟩, h, rfl⟩ tfae_finish diff --git a/Mathlib/RingTheory/Bezout.lean b/Mathlib/RingTheory/Bezout.lean index 4ef7731887a6d..37aef0df9ae66 100644 --- a/Mathlib/RingTheory/Bezout.lean +++ b/Mathlib/RingTheory/Bezout.lean @@ -51,13 +51,13 @@ theorem TFAE [IsBezout R] [IsDomain R] : [IsNoetherianRing R, IsPrincipalIdealRing R, UniqueFactorizationMonoid R, WfDvdMonoid R] := by classical tfae_have 1 → 2 - · intro H; exact ⟨fun I => isPrincipal_of_FG _ (IsNoetherian.noetherian _)⟩ + | H => ⟨fun I => isPrincipal_of_FG _ (IsNoetherian.noetherian _)⟩ tfae_have 2 → 3 - · intro; infer_instance + | _ => inferInstance tfae_have 3 → 4 - · intro; infer_instance + | _ => inferInstance tfae_have 4 → 1 - · rintro ⟨h⟩ + | ⟨h⟩ => by rw [isNoetherianRing_iff, isNoetherian_iff_fg_wellFounded] refine ⟨RelEmbedding.wellFounded ?_ h⟩ have : ∀ I : { J : Ideal R // J.FG }, ∃ x : R, (I : Ideal R) = Ideal.span {x} := diff --git a/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean b/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean index 48cab27dd47c2..b3171e5b848cd 100644 --- a/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean +++ b/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean @@ -166,23 +166,17 @@ theorem tfae_of_isNoetherianRing_of_localRing_of_isDomain (maximalIdeal R).IsPrincipal, finrank (ResidueField R) (CotangentSpace R) ≤ 1, ∀ (I) (_ : I ≠ ⊥), ∃ n : ℕ, I = maximalIdeal R ^ n] := by - tfae_have 1 → 2 - · exact fun _ ↦ inferInstance - tfae_have 2 → 1 - · exact fun _ ↦ ((IsBezout.TFAE (R := R)).out 0 1).mp ‹_› + tfae_have 1 → 2 := fun _ ↦ inferInstance + tfae_have 2 → 1 := fun _ ↦ ((IsBezout.TFAE (R := R)).out 0 1).mp ‹_› tfae_have 1 → 4 - · intro H - exact ⟨inferInstance, fun P hP hP' ↦ eq_maximalIdeal (hP'.isMaximal hP)⟩ - tfae_have 4 → 3 - · exact fun ⟨h₁, h₂⟩ ↦ { h₁ with maximalOfPrime := (h₂ _ · · ▸ maximalIdeal.isMaximal R) } - tfae_have 3 → 5 - · exact fun h ↦ maximalIdeal_isPrincipal_of_isDedekindDomain R - tfae_have 6 ↔ 5 - · exact finrank_cotangentSpace_le_one_iff - tfae_have 5 → 7 - · exact exists_maximalIdeal_pow_eq_of_principal R - tfae_have 7 → 2 - · rw [ValuationRing.iff_ideal_total] + | H => ⟨inferInstance, fun P hP hP' ↦ eq_maximalIdeal (hP'.isMaximal hP)⟩ + tfae_have 4 → 3 := + fun ⟨h₁, h₂⟩ ↦ { h₁ with maximalOfPrime := (h₂ _ · · ▸ maximalIdeal.isMaximal R) } + tfae_have 3 → 5 := fun h ↦ maximalIdeal_isPrincipal_of_isDedekindDomain R + tfae_have 6 ↔ 5 := finrank_cotangentSpace_le_one_iff + tfae_have 5 → 7 := exists_maximalIdeal_pow_eq_of_principal R + tfae_have 7 → 2 := by + rw [ValuationRing.iff_ideal_total] intro H constructor intro I J diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index bef434517f9b0..e90cd0987d45c 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -125,14 +125,12 @@ theorem tfae_equational_criterion : List.TFAE [ ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0] := by classical - tfae_have 1 ↔ 2 - · exact iff_rTensor_injective' R M - tfae_have 3 ↔ 2 - · exact forall_vanishesTrivially_iff_forall_rTensor_injective R - tfae_have 3 ↔ 4 - · simp [(TensorProduct.lid R M).injective.eq_iff.symm, isTrivialRelation_iff_vanishesTrivially] + tfae_have 1 ↔ 2 := iff_rTensor_injective' R M + tfae_have 3 ↔ 2 := forall_vanishesTrivially_iff_forall_rTensor_injective R + tfae_have 3 ↔ 4 := by + simp [(TensorProduct.lid R M).injective.eq_iff.symm, isTrivialRelation_iff_vanishesTrivially] tfae_have 4 → 5 - · intro h₄ ι hι f x hfx + | h₄, ι, hι, f, x, hfx => by let f' : ι → R := f let x' : ι → M := fun i ↦ x (single i 1) have := calc @@ -154,7 +152,7 @@ theorem tfae_equational_criterion : List.TFAE [ simp only [linearCombination_apply, zero_smul, implies_true, sum_fintype, finset_sum_apply] exact ha' j tfae_have 5 → 4 - · intro h₅ ι hi f x hfx + | h₅, ι, hi, f, x, hfx => by let f' : ι →₀ R := equivFunOnFinite.symm f let x' : (ι →₀ R) →ₗ[R] M := Finsupp.linearCombination R x have : x' f' = 0 := by simpa [x', f', linearCombination_apply, sum_fintype] using hfx @@ -167,7 +165,7 @@ theorem tfae_equational_criterion : List.TFAE [ ← (fun _ ↦ equivFunOnFinite_symm_apply_toFun _ _ : ∀ x, f' x = f x), univ_sum_single] simpa using DFunLike.congr_fun ha' j tfae_have 5 → 6 - · intro h₅ N _ _ _ _ f x hfx + | h₅, N, _, _, _, _, f, x, hfx => by have ϕ := Module.Free.repr R N have : (x ∘ₗ ϕ.symm) (ϕ f) = 0 := by simpa obtain ⟨κ, hκ, a', y, ha'y, ha'⟩ := h₅ this @@ -175,8 +173,7 @@ theorem tfae_equational_criterion : List.TFAE [ · simpa [LinearMap.comp_assoc] using congrArg (fun g ↦ (g ∘ₗ ϕ : N →ₗ[R] M)) ha'y · simpa using ha' tfae_have 6 → 5 - · intro h₆ _ _ _ _ hfx - exact h₆ hfx + | h₆, _, _, _, _, hfx => h₆ hfx tfae_finish /-- **Equational criterion for flatness** [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK). diff --git a/Mathlib/RingTheory/Henselian.lean b/Mathlib/RingTheory/Henselian.lean index 18e8607dbc93a..ab874dcea2329 100644 --- a/Mathlib/RingTheory/Henselian.lean +++ b/Mathlib/RingTheory/Henselian.lean @@ -121,10 +121,9 @@ theorem HenselianLocalRing.TFAE (R : Type u) [CommRing R] [LocalRing R] : ∀ (φ : R →+* K), Surjective φ → ∀ f : R[X], f.Monic → ∀ a₀ : K, f.eval₂ φ a₀ = 0 → f.derivative.eval₂ φ a₀ ≠ 0 → ∃ a : R, f.IsRoot a ∧ φ a = a₀] := by tfae_have 3 → 2 - · intro H - exact H (residue R) Ideal.Quotient.mk_surjective + | H => H (residue R) Ideal.Quotient.mk_surjective tfae_have 2 → 1 - · intro H + | H => by constructor intro f hf a₀ h₁ h₂ specialize H f hf (residue R a₀) @@ -136,7 +135,7 @@ theorem HenselianLocalRing.TFAE (R : Type u) [CommRing R] [LocalRing R] : rw [← Ideal.Quotient.eq_zero_iff_mem] rwa [← sub_eq_zero, ← RingHom.map_sub] at ha₂ tfae_have 1 → 3 - · intro hR K _K φ hφ f hf a₀ h₁ h₂ + | hR, K, _K, φ, hφ, f, hf, a₀, h₁, h₂ => by obtain ⟨a₀, rfl⟩ := hφ a₀ have H := HenselianLocalRing.is_henselian f hf a₀ simp only [← ker_eq_maximalIdeal φ hφ, eval₂_at_apply, RingHom.mem_ker φ] at H h₁ h₂ diff --git a/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean b/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean index fc9ea8c3bc6a3..7dd4c8dade367 100644 --- a/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean +++ b/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean @@ -97,22 +97,13 @@ theorem local_hom_TFAE (f : R →+* S) : (maximalIdeal R).map f ≤ maximalIdeal S, maximalIdeal R ≤ (maximalIdeal S).comap f, (maximalIdeal S).comap f = maximalIdeal R] := by tfae_have 1 → 2 - · rintro _ _ ⟨a, ha, rfl⟩ - exact map_nonunit f a ha - tfae_have 2 → 4 - · exact Set.image_subset_iff.1 - tfae_have 3 ↔ 4 - · exact Ideal.map_le_iff_le_comap - tfae_have 4 → 1 - · intro h - constructor - exact fun x => not_imp_not.1 (@h x) + | _, _, ⟨a, ha, rfl⟩ => map_nonunit f a ha + tfae_have 2 → 4 := Set.image_subset_iff.1 + tfae_have 3 ↔ 4 := Ideal.map_le_iff_le_comap + tfae_have 4 → 1 := fun h ↦ ⟨fun x => not_imp_not.1 (@h x)⟩ tfae_have 1 → 5 - · intro - ext - exact not_iff_not.2 (isUnit_map_iff f _) - tfae_have 5 → 4 - · exact fun h => le_of_eq h.symm + | _ => by ext; exact not_iff_not.2 (isUnit_map_iff f _) + tfae_have 5 → 4 := fun h ↦ le_of_eq h.symm tfae_finish end diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index c64c33a0023cf..77bb5ceacdaaf 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -506,10 +506,10 @@ theorem isEquiv_tfae [LinearOrderedCommGroupWithZero Γ₀] [LinearOrderedCommGr (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : [v.IsEquiv v', ∀ {x}, v x ≤ 1 ↔ v' x ≤ 1, ∀ {x}, v x = 1 ↔ v' x = 1, ∀ {x}, v x < 1 ↔ v' x < 1, ∀ {x}, v (x - 1) < 1 ↔ v' (x - 1) < 1].TFAE := by - tfae_have 1 ↔ 2; · apply isEquiv_iff_val_le_one - tfae_have 1 ↔ 3; · apply isEquiv_iff_val_eq_one - tfae_have 1 ↔ 4; · apply isEquiv_iff_val_lt_one - tfae_have 1 ↔ 5; · apply isEquiv_iff_val_sub_one_lt_one + tfae_have 1 ↔ 2 := isEquiv_iff_val_le_one .. + tfae_have 1 ↔ 3 := isEquiv_iff_val_eq_one .. + tfae_have 1 ↔ 4 := isEquiv_iff_val_lt_one .. + tfae_have 1 ↔ 5 := isEquiv_iff_val_sub_one_lt_one .. tfae_finish end diff --git a/Mathlib/RingTheory/Valuation/ValuationRing.lean b/Mathlib/RingTheory/Valuation/ValuationRing.lean index 3aa7cd60c9a41..864d73e5b39e6 100644 --- a/Mathlib/RingTheory/Valuation/ValuationRing.lean +++ b/Mathlib/RingTheory/Valuation/ValuationRing.lean @@ -363,10 +363,10 @@ protected theorem TFAE (R : Type u) [CommRing R] [IsDomain R] : [ValuationRing R, ∀ x : FractionRing R, IsLocalization.IsInteger R x ∨ IsLocalization.IsInteger R x⁻¹, IsTotal R (· ∣ ·), IsTotal (Ideal R) (· ≤ ·), LocalRing R ∧ IsBezout R] := by - tfae_have 1 ↔ 2; · exact iff_isInteger_or_isInteger R _ - tfae_have 1 ↔ 3; · exact iff_dvd_total - tfae_have 1 ↔ 4; · exact iff_ideal_total - tfae_have 1 ↔ 5; · exact iff_local_bezout_domain + tfae_have 1 ↔ 2 := iff_isInteger_or_isInteger R _ + tfae_have 1 ↔ 3 := iff_dvd_total + tfae_have 1 ↔ 4 := iff_ideal_total + tfae_have 1 ↔ 5 := iff_local_bezout_domain tfae_finish end diff --git a/Mathlib/SetTheory/Ordinal/Topology.lean b/Mathlib/SetTheory/Ordinal/Topology.lean index 3f648546cba25..73e5ab814961e 100644 --- a/Mathlib/SetTheory/Ordinal/Topology.lean +++ b/Mathlib/SetTheory/Ordinal/Topology.lean @@ -87,19 +87,19 @@ theorem mem_closure_tfae (a : Ordinal.{u}) (s : Set Ordinal) : ∃ (o : Ordinal.{u}), o ≠ 0 ∧ ∃ (f : ∀ x < o, Ordinal), (∀ x hx, f x hx ∈ s) ∧ bsup.{u, u} o f = a, ∃ (ι : Type u), Nonempty ι ∧ ∃ f : ι → Ordinal, (∀ i, f i ∈ s) ∧ ⨆ i, f i = a] := by - tfae_have 1 → 2 - · simp only [mem_closure_iff_nhdsWithin_neBot, inter_comm s, nhdsWithin_inter', nhds_left_eq_nhds] + tfae_have 1 → 2 := by + simp only [mem_closure_iff_nhdsWithin_neBot, inter_comm s, nhdsWithin_inter', nhds_left_eq_nhds] exact id tfae_have 2 → 3 - · intro h + | h => by rcases (s ∩ Iic a).eq_empty_or_nonempty with he | hne · simp [he] at h · refine ⟨hne, (isLUB_of_mem_closure ?_ h).csSup_eq hne⟩ exact fun x hx => hx.2 tfae_have 3 → 4 - · exact fun h => ⟨_, inter_subset_left, h.1, bddAbove_Iic.mono inter_subset_right, h.2⟩ - tfae_have 4 → 5 - · rintro ⟨t, hts, hne, hbdd, rfl⟩ + | h => ⟨_, inter_subset_left, h.1, bddAbove_Iic.mono inter_subset_right, h.2⟩ + tfae_have 4 → 5 := by + rintro ⟨t, hts, hne, hbdd, rfl⟩ have hlub : IsLUB t (sSup t) := isLUB_csSup hne hbdd let ⟨y, hyt⟩ := hne classical @@ -109,11 +109,11 @@ theorem mem_closure_tfae (a : Ordinal.{u}) (s : Set Ordinal) : · refine le_antisymm (bsup_le fun x _ => ?_) (csSup_le hne fun x hx => ?_) · split_ifs <;> exact hlub.1 ‹_› · refine (if_pos hx).symm.trans_le (le_bsup _ _ <| (hlub.1 hx).trans_lt (lt_succ _)) - tfae_have 5 → 6 - · rintro ⟨o, h₀, f, hfs, rfl⟩ + tfae_have 5 → 6 := by + rintro ⟨o, h₀, f, hfs, rfl⟩ exact ⟨_, toType_nonempty_iff_ne_zero.2 h₀, familyOfBFamily o f, fun _ => hfs _ _, rfl⟩ - tfae_have 6 → 1 - · rintro ⟨ι, hne, f, hfs, rfl⟩ + tfae_have 6 → 1 := by + rintro ⟨ι, hne, f, hfs, rfl⟩ exact closure_mono (range_subset_iff.2 hfs) <| csSup_mem_closure (range_nonempty f) (bddAbove_range.{u, u} f) tfae_finish diff --git a/Mathlib/Topology/Algebra/Group/SubmonoidClosure.lean b/Mathlib/Topology/Algebra/Group/SubmonoidClosure.lean index 1b86b845e840f..ae23b4d9c3b9b 100644 --- a/Mathlib/Topology/Algebra/Group/SubmonoidClosure.lean +++ b/Mathlib/Topology/Algebra/Group/SubmonoidClosure.lean @@ -61,15 +61,15 @@ theorem mapClusterPt_atTop_pow_tfae (x y : G) : x ∈ closure (range (y ^ · : ℕ → G)), x ∈ closure (range (y ^ · : ℤ → G)), ] := by - tfae_have 2 ↔ 1; exact mapClusterPt_atTop_zpow_iff_pow - tfae_have 3 → 4 - · refine fun h ↦ closure_mono (range_subset_iff.2 fun n ↦ ?_) h + tfae_have 2 ↔ 1 := mapClusterPt_atTop_zpow_iff_pow + tfae_have 3 → 4 := by + refine fun h ↦ closure_mono (range_subset_iff.2 fun n ↦ ?_) h exact ⟨n, zpow_natCast _ _⟩ - tfae_have 4 → 1 - · refine fun h ↦ closure_minimal ?_ isClosed_setOf_clusterPt h + tfae_have 4 → 1 := by + refine fun h ↦ closure_minimal ?_ isClosed_setOf_clusterPt h exact range_subset_iff.2 (mapClusterPt_self_zpow_atTop_pow _) - tfae_have 1 → 3 - · rw [mem_closure_iff_clusterPt] + tfae_have 1 → 3 := by + rw [mem_closure_iff_clusterPt] exact (ClusterPt.mono · (le_principal_iff.2 range_mem_map)) tfae_finish diff --git a/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean b/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean index c6517bf9f086a..11338ba0c53d7 100644 --- a/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean @@ -41,12 +41,9 @@ theorem effectiveEpi_tfae , Epi π , Function.Surjective π ] := by - tfae_have 1 → 2 - · intro; infer_instance - tfae_have 2 ↔ 3 - · exact epi_iff_surjective π - tfae_have 3 → 1 - · exact fun hπ ↦ ⟨⟨effectiveEpiStruct π hπ⟩⟩ + tfae_have 1 → 2 := fun _ ↦ inferInstance + tfae_have 2 ↔ 3 := epi_iff_surjective π + tfae_have 3 → 1 := fun hπ ↦ ⟨⟨effectiveEpiStruct π hπ⟩⟩ tfae_finish instance : Preregular CompHaus := @@ -65,12 +62,12 @@ theorem effectiveEpiFamily_tfae , ∀ b : B, ∃ (a : α) (x : X a), π a x = b ] := by tfae_have 2 → 1 - · intro + | _ => by simpa [← effectiveEpi_desc_iff_effectiveEpiFamily, (effectiveEpi_tfae (Sigma.desc π)).out 0 1] tfae_have 1 → 2 - · intro; infer_instance + | _ => inferInstance tfae_have 3 → 2 - · intro e + | e => by rw [epi_iff_surjective] intro b obtain ⟨t, x, h⟩ := e b @@ -78,7 +75,8 @@ theorem effectiveEpiFamily_tfae change (Sigma.ι X t ≫ Sigma.desc π) x = _ simpa using h tfae_have 2 → 3 - · intro e; rw [epi_iff_surjective] at e + | e => by + rw [epi_iff_surjective] at e let i : ∐ X ≅ finiteCoproduct X := (colimit.isColimit _).coconePointUniqueUpToIso (finiteCoproduct.isColimit _) intro b diff --git a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean index 251da0eb75003..f6a2c77737320 100644 --- a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean @@ -37,12 +37,9 @@ theorem effectiveEpi_tfae , Epi π , Function.Surjective π ] := by - tfae_have 1 → 2 - · intro; infer_instance - tfae_have 2 ↔ 3 - · exact epi_iff_surjective π - tfae_have 3 → 1 - · exact fun hπ ↦ ⟨⟨CompHausLike.effectiveEpiStruct π hπ⟩⟩ + tfae_have 1 → 2 := fun _ ↦ inferInstance + tfae_have 2 ↔ 3 := epi_iff_surjective π + tfae_have 3 → 1 := fun hπ ↦ ⟨⟨CompHausLike.effectiveEpiStruct π hπ⟩⟩ tfae_finish instance : profiniteToCompHaus.PreservesEffectiveEpis where @@ -80,12 +77,11 @@ theorem effectiveEpiFamily_tfae , ∀ b : B, ∃ (a : α) (x : X a), π a x = b ] := by tfae_have 2 → 1 - · intro + | _ => by simpa [← effectiveEpi_desc_iff_effectiveEpiFamily, (effectiveEpi_tfae (Sigma.desc π)).out 0 1] - tfae_have 1 → 2 - · intro; infer_instance - tfae_have 3 ↔ 1 - · erw [((CompHaus.effectiveEpiFamily_tfae + tfae_have 1 → 2 := fun _ ↦ inferInstance + tfae_have 3 ↔ 1 := by + erw [((CompHaus.effectiveEpiFamily_tfae (fun a ↦ profiniteToCompHaus.obj (X a)) (fun a ↦ profiniteToCompHaus.map (π a))).out 2 0 : )] exact ⟨fun h ↦ profiniteToCompHaus.finite_effectiveEpiFamily_of_map _ _ h, fun _ ↦ inferInstance⟩ diff --git a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean index ff4d234dae338..1901963fcc1a9 100644 --- a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean @@ -36,12 +36,9 @@ theorem effectiveEpi_tfae , Epi π , Function.Surjective π ] := by - tfae_have 1 → 2 - · intro; infer_instance - tfae_have 2 ↔ 3 - · exact epi_iff_surjective π - tfae_have 3 → 1 - · exact fun hπ ↦ ⟨⟨effectiveEpiStruct π hπ⟩⟩ + tfae_have 1 → 2 := fun _ ↦ inferInstance + tfae_have 2 ↔ 3 := epi_iff_surjective π + tfae_have 3 → 1 := fun hπ ↦ ⟨⟨effectiveEpiStruct π hπ⟩⟩ tfae_finish instance : Stonean.toCompHaus.PreservesEffectiveEpis where @@ -81,12 +78,11 @@ theorem effectiveEpiFamily_tfae , ∀ b : B, ∃ (a : α) (x : X a), π a x = b ] := by tfae_have 2 → 1 - · intro + | _ => by simpa [← effectiveEpi_desc_iff_effectiveEpiFamily, (effectiveEpi_tfae (Sigma.desc π)).out 0 1] - tfae_have 1 → 2 - · intro; infer_instance - tfae_have 3 ↔ 1 - · erw [((CompHaus.effectiveEpiFamily_tfae + tfae_have 1 → 2 := fun _ ↦ inferInstance + tfae_have 3 ↔ 1 := by + erw [((CompHaus.effectiveEpiFamily_tfae (fun a ↦ Stonean.toCompHaus.obj (X a)) (fun a ↦ Stonean.toCompHaus.map (π a))).out 2 0 : )] exact ⟨fun h ↦ Stonean.toCompHaus.finite_effectiveEpiFamily_of_map _ _ h, fun _ ↦ inferInstance⟩ diff --git a/Mathlib/Topology/Inseparable.lean b/Mathlib/Topology/Inseparable.lean index f4f888556c776..392ac4f52c773 100644 --- a/Mathlib/Topology/Inseparable.lean +++ b/Mathlib/Topology/Inseparable.lean @@ -53,20 +53,15 @@ theorem specializes_TFAE (x y : X) : y ∈ closure ({ x } : Set X), closure ({ y } : Set X) ⊆ closure { x }, ClusterPt y (pure x)] := by - tfae_have 1 → 2 - · exact (pure_le_nhds _).trans - tfae_have 2 → 3 - · exact fun h s hso hy => h (hso.mem_nhds hy) - tfae_have 3 → 4 - · exact fun h s hsc hx => of_not_not fun hy => h sᶜ hsc.isOpen_compl hy hx - tfae_have 4 → 5 - · exact fun h => h _ isClosed_closure (subset_closure <| mem_singleton _) - tfae_have 6 ↔ 5 - · exact isClosed_closure.closure_subset_iff.trans singleton_subset_iff - tfae_have 5 ↔ 7 - · rw [mem_closure_iff_clusterPt, principal_singleton] - tfae_have 5 → 1 - · refine fun h => (nhds_basis_opens _).ge_iff.2 ?_ + tfae_have 1 → 2 := (pure_le_nhds _).trans + tfae_have 2 → 3 := fun h s hso hy => h (hso.mem_nhds hy) + tfae_have 3 → 4 := fun h s hsc hx => of_not_not fun hy => h sᶜ hsc.isOpen_compl hy hx + tfae_have 4 → 5 := fun h => h _ isClosed_closure (subset_closure <| mem_singleton _) + tfae_have 6 ↔ 5 := isClosed_closure.closure_subset_iff.trans singleton_subset_iff + tfae_have 5 ↔ 7 := by + rw [mem_closure_iff_clusterPt, principal_singleton] + tfae_have 5 → 1 := by + refine fun h => (nhds_basis_opens _).ge_iff.2 ?_ rintro s ⟨hy, ho⟩ rcases mem_closure_iff.1 h s ho hy with ⟨z, hxs, rfl : z = x⟩ exact ho.mem_nhds hxs diff --git a/Mathlib/Topology/LocallyClosed.lean b/Mathlib/Topology/LocallyClosed.lean index 2cb3f5399de36..fd260f0e11c03 100644 --- a/Mathlib/Topology/LocallyClosed.lean +++ b/Mathlib/Topology/LocallyClosed.lean @@ -150,8 +150,8 @@ lemma isLocallyClosed_tfae (s : Set X) : ∀ x ∈ s, ∃ U ∈ 𝓝 x, IsClosed (U ↓∩ s), ∀ x ∈ s, ∃ U, x ∈ U ∧ IsOpen U ∧ U ∩ closure s ⊆ s, IsOpen (closure s ↓∩ s)] := by - tfae_have 1 → 2 - · rintro ⟨U, Z, hU, hZ, rfl⟩ + tfae_have 1 → 2 := by + rintro ⟨U, Z, hU, hZ, rfl⟩ have : Z ∪ (frontier (U ∩ Z))ᶜ = univ := by nth_rw 1 [← hZ.closure_eq] rw [← compl_subset_iff_union, compl_subset_compl] @@ -160,23 +160,23 @@ lemma isLocallyClosed_tfae (s : Set X) : inter_univ] exact hU.union isClosed_frontier.isOpen_compl tfae_have 2 → 3 - · exact fun h x ↦ (⟨coborder s, h.mem_nhds <| subset_coborder ·, isClosed_preimage_val_coborder⟩) + | h, x => (⟨coborder s, h.mem_nhds <| subset_coborder ·, isClosed_preimage_val_coborder⟩) tfae_have 3 → 4 - · intro h x hx + | h, x, hx => by obtain ⟨t, ht, ht'⟩ := h x hx obtain ⟨U, hUt, hU, hxU⟩ := mem_nhds_iff.mp ht rw [isClosed_preimage_val] at ht' exact ⟨U, hxU, hU, (subset_inter (inter_subset_left.trans hUt) (hU.inter_closure.trans (closure_mono <| inter_subset_inter hUt subset_rfl))).trans ht'⟩ tfae_have 4 → 5 - · intro H + | H => by choose U hxU hU e using H refine ⟨⋃ x ∈ s, U x ‹_›, isOpen_iUnion (isOpen_iUnion <| hU ·), ext fun x ↦ ⟨?_, ?_⟩⟩ · rintro ⟨_, ⟨⟨y, rfl⟩, ⟨_, ⟨hy, rfl⟩, hxU⟩⟩⟩ exact e y hy ⟨hxU, x.2⟩ · exact (subset_iUnion₂ _ _ <| hxU x ·) tfae_have 5 → 1 - · intro H + | H => by convert H.isLocallyClosed.image inducing_subtype_val (by simpa using isClosed_closure.isLocallyClosed) simpa using subset_closure diff --git a/Mathlib/Topology/LocallyConstant/Basic.lean b/Mathlib/Topology/LocallyConstant/Basic.lean index bc918bf4803b5..401cf78da5d19 100644 --- a/Mathlib/Topology/LocallyConstant/Basic.lean +++ b/Mathlib/Topology/LocallyConstant/Basic.lean @@ -39,18 +39,15 @@ protected theorem tfae (f : X → Y) : ∀ x, IsOpen { x' | f x' = f x }, ∀ y, IsOpen (f ⁻¹' {y}), ∀ x, ∃ U : Set X, IsOpen U ∧ x ∈ U ∧ ∀ x' ∈ U, f x' = f x] := by - tfae_have 1 → 4 - · exact fun h y => h {y} - tfae_have 4 → 3 - · exact fun h x => h (f x) - tfae_have 3 → 2 - · exact fun h x => IsOpen.mem_nhds (h x) rfl + tfae_have 1 → 4 := fun h y => h {y} + tfae_have 4 → 3 := fun h x => h (f x) + tfae_have 3 → 2 := fun h x => IsOpen.mem_nhds (h x) rfl tfae_have 2 → 5 - · intro h x + | h, x => by rcases mem_nhds_iff.1 (h x) with ⟨U, eq, hU, hx⟩ exact ⟨U, hU, hx, eq⟩ tfae_have 5 → 1 - · intro h s + | h, s => by refine isOpen_iff_forall_mem_open.2 fun x hx ↦ ?_ rcases h x with ⟨U, hU, hxU, eq⟩ exact ⟨U, fun x' hx' => mem_preimage.2 <| (eq x' hx').symm ▸ hx, hU, hxU⟩ diff --git a/Mathlib/Topology/NoetherianSpace.lean b/Mathlib/Topology/NoetherianSpace.lean index 74d4532b5976c..88d07a7493deb 100644 --- a/Mathlib/Topology/NoetherianSpace.lean +++ b/Mathlib/Topology/NoetherianSpace.lean @@ -81,15 +81,12 @@ theorem noetherianSpace_TFAE : WellFounded fun s t : Closeds α => s < t, ∀ s : Set α, IsCompact s, ∀ s : Opens α, IsCompact (s : Set α)] := by - tfae_have 1 ↔ 2 - · refine (noetherianSpace_iff α).trans (Opens.compl_bijective.2.wellFounded_iff ?_) + tfae_have 1 ↔ 2 := by + refine (noetherianSpace_iff α).trans (Opens.compl_bijective.2.wellFounded_iff ?_) exact (@OrderIso.compl (Set α)).lt_iff_lt.symm - tfae_have 1 ↔ 4 - · exact noetherianSpace_iff_opens α - tfae_have 1 → 3 - · exact @NoetherianSpace.isCompact α _ - tfae_have 3 → 4 - · exact fun h s => h s + tfae_have 1 ↔ 4 := noetherianSpace_iff_opens α + tfae_have 1 → 3 := @NoetherianSpace.isCompact α _ + tfae_have 3 → 4 := fun h s => h s tfae_finish variable {α} diff --git a/Mathlib/Topology/Order/LeftRightNhds.lean b/Mathlib/Topology/Order/LeftRightNhds.lean index c44a1895b3c19..c6f61ba355838 100644 --- a/Mathlib/Topology/Order/LeftRightNhds.lean +++ b/Mathlib/Topology/Order/LeftRightNhds.lean @@ -43,17 +43,15 @@ theorem TFAE_mem_nhdsWithin_Ioi {a b : α} (hab : a < b) (s : Set α) : s ∈ 𝓝[Ioo a b] a, ∃ u ∈ Ioc a b, Ioo a u ⊆ s, ∃ u ∈ Ioi a, Ioo a u ⊆ s] := by - tfae_have 1 ↔ 2 - · rw [nhdsWithin_Ioc_eq_nhdsWithin_Ioi hab] - tfae_have 1 ↔ 3 - · rw [nhdsWithin_Ioo_eq_nhdsWithin_Ioi hab] - tfae_have 4 → 5 - · exact fun ⟨u, umem, hu⟩ => ⟨u, umem.1, hu⟩ + tfae_have 1 ↔ 2 := by + rw [nhdsWithin_Ioc_eq_nhdsWithin_Ioi hab] + tfae_have 1 ↔ 3 := by + rw [nhdsWithin_Ioo_eq_nhdsWithin_Ioi hab] + tfae_have 4 → 5 := fun ⟨u, umem, hu⟩ => ⟨u, umem.1, hu⟩ tfae_have 5 → 1 - · rintro ⟨u, hau, hu⟩ - exact mem_of_superset (Ioo_mem_nhdsWithin_Ioi ⟨le_refl a, hau⟩) hu + | ⟨u, hau, hu⟩ => mem_of_superset (Ioo_mem_nhdsWithin_Ioi ⟨le_refl a, hau⟩) hu tfae_have 1 → 4 - · intro h + | h => by rcases mem_nhdsWithin_iff_exists_mem_nhds_inter.1 h with ⟨v, va, hv⟩ rcases exists_Ico_subset_of_mem_nhds' va hab with ⟨u, au, hu⟩ exact ⟨u, au, fun x hx => hv ⟨hu ⟨le_of_lt hx.1, hx.2⟩, hx.1⟩⟩ @@ -183,19 +181,15 @@ theorem TFAE_mem_nhdsWithin_Ici {a b : α} (hab : a < b) (s : Set α) : s ∈ 𝓝[Ico a b] a, ∃ u ∈ Ioc a b, Ico a u ⊆ s, ∃ u ∈ Ioi a , Ico a u ⊆ s] := by - tfae_have 1 ↔ 2 - · rw [nhdsWithin_Icc_eq_nhdsWithin_Ici hab] - tfae_have 1 ↔ 3 - · rw [nhdsWithin_Ico_eq_nhdsWithin_Ici hab] - tfae_have 1 ↔ 5 - · exact (nhdsWithin_Ici_basis' ⟨b, hab⟩).mem_iff - tfae_have 4 → 5 - · exact fun ⟨u, umem, hu⟩ => ⟨u, umem.1, hu⟩ + tfae_have 1 ↔ 2 := by + rw [nhdsWithin_Icc_eq_nhdsWithin_Ici hab] + tfae_have 1 ↔ 3 := by + rw [nhdsWithin_Ico_eq_nhdsWithin_Ici hab] + tfae_have 1 ↔ 5 := (nhdsWithin_Ici_basis' ⟨b, hab⟩).mem_iff + tfae_have 4 → 5 := fun ⟨u, umem, hu⟩ => ⟨u, umem.1, hu⟩ tfae_have 5 → 4 - · rintro ⟨u, hua, hus⟩ - exact - ⟨min u b, ⟨lt_min hua hab, min_le_right _ _⟩, - (Ico_subset_Ico_right <| min_le_left _ _).trans hus⟩ + | ⟨u, hua, hus⟩ => ⟨min u b, ⟨lt_min hua hab, min_le_right _ _⟩, + (Ico_subset_Ico_right <| min_le_left _ _).trans hus⟩ tfae_finish theorem mem_nhdsWithin_Ici_iff_exists_mem_Ioc_Ico_subset {a u' : α} {s : Set α} (hu' : a < u') : diff --git a/Mathlib/Topology/Separation.lean b/Mathlib/Topology/Separation.lean index b87d9628b0774..500bae87ab25c 100644 --- a/Mathlib/Topology/Separation.lean +++ b/Mathlib/Topology/Separation.lean @@ -576,30 +576,28 @@ theorem t1Space_TFAE (X : Type u) [TopologicalSpace X] : ∀ ⦃x y : X⦄, x ≠ y → Disjoint (𝓝 x) (pure y), ∀ ⦃x y : X⦄, x ≠ y → Disjoint (pure x) (𝓝 y), ∀ ⦃x y : X⦄, x ⤳ y → x = y] := by - tfae_have 1 ↔ 2 - · exact ⟨fun h => h.1, fun h => ⟨h⟩⟩ - tfae_have 2 ↔ 3 - · simp only [isOpen_compl_iff] - tfae_have 5 ↔ 3 - · refine forall_swap.trans ?_ + tfae_have 1 ↔ 2 := ⟨fun h => h.1, fun h => ⟨h⟩⟩ + tfae_have 2 ↔ 3 := by + simp only [isOpen_compl_iff] + tfae_have 5 ↔ 3 := by + refine forall_swap.trans ?_ simp only [isOpen_iff_mem_nhds, mem_compl_iff, mem_singleton_iff] - tfae_have 5 ↔ 6 - · simp only [← subset_compl_singleton_iff, exists_mem_subset_iff] - tfae_have 5 ↔ 7 - · simp only [(nhds_basis_opens _).mem_iff, subset_compl_singleton_iff, exists_prop, and_assoc, + tfae_have 5 ↔ 6 := by + simp only [← subset_compl_singleton_iff, exists_mem_subset_iff] + tfae_have 5 ↔ 7 := by + simp only [(nhds_basis_opens _).mem_iff, subset_compl_singleton_iff, exists_prop, and_assoc, and_left_comm] - tfae_have 5 ↔ 8 - · simp only [← principal_singleton, disjoint_principal_right] - tfae_have 8 ↔ 9 - · exact forall_swap.trans (by simp only [disjoint_comm, ne_comm]) - tfae_have 1 → 4 - · simp only [continuous_def, CofiniteTopology.isOpen_iff'] + tfae_have 5 ↔ 8 := by + simp only [← principal_singleton, disjoint_principal_right] + tfae_have 8 ↔ 9 := forall_swap.trans (by simp only [disjoint_comm, ne_comm]) + tfae_have 1 → 4 := by + simp only [continuous_def, CofiniteTopology.isOpen_iff'] rintro H s (rfl | hs) exacts [isOpen_empty, compl_compl s ▸ (@Set.Finite.isClosed _ _ H _ hs).isOpen_compl] - tfae_have 4 → 2 - · exact fun h x => (CofiniteTopology.isClosed_iff.2 <| Or.inr (finite_singleton _)).preimage h - tfae_have 2 ↔ 10 - · simp only [← closure_subset_iff_isClosed, specializes_iff_mem_closure, subset_def, + tfae_have 4 → 2 := + fun h x => (CofiniteTopology.isClosed_iff.2 <| Or.inr (finite_singleton _)).preimage h + tfae_have 2 ↔ 10 := by + simp only [← closure_subset_iff_isClosed, specializes_iff_mem_closure, subset_def, mem_singleton_iff, eq_comm] tfae_finish @@ -1890,30 +1888,28 @@ theorem regularSpace_TFAE (X : Type u) [TopologicalSpace X] : ∀ (x : X) (s : Set X), s ∈ 𝓝 x → ∃ t ∈ 𝓝 x, IsClosed t ∧ t ⊆ s, ∀ x : X, (𝓝 x).lift' closure ≤ 𝓝 x, ∀ x : X , (𝓝 x).lift' closure = 𝓝 x] := by - tfae_have 1 ↔ 5 - · rw [regularSpace_iff, (@compl_surjective (Set X) _).forall, forall_swap] + tfae_have 1 ↔ 5 := by + rw [regularSpace_iff, (@compl_surjective (Set X) _).forall, forall_swap] simp only [isClosed_compl_iff, mem_compl_iff, Classical.not_not, @and_comm (_ ∈ _), (nhds_basis_opens _).lift'_closure.le_basis_iff (nhds_basis_opens _), and_imp, (nhds_basis_opens _).disjoint_iff_right, exists_prop, ← subset_interior_iff_mem_nhdsSet, interior_compl, compl_subset_compl] - tfae_have 5 → 6 - · exact fun h a => (h a).antisymm (𝓝 _).le_lift'_closure + tfae_have 5 → 6 := fun h a => (h a).antisymm (𝓝 _).le_lift'_closure tfae_have 6 → 4 - · intro H a s hs + | H, a, s, hs => by rw [← H] at hs rcases (𝓝 a).basis_sets.lift'_closure.mem_iff.mp hs with ⟨U, hU, hUs⟩ exact ⟨closure U, mem_of_superset hU subset_closure, isClosed_closure, hUs⟩ tfae_have 4 → 2 - · intro H s a ha + | H, s, a, ha => by have ha' : sᶜ ∈ 𝓝 a := by rwa [← mem_interior_iff_mem_nhds, interior_compl] rcases H _ _ ha' with ⟨U, hU, hUc, hUs⟩ refine disjoint_of_disjoint_of_mem disjoint_compl_left ?_ hU rwa [← subset_interior_iff_mem_nhdsSet, hUc.isOpen_compl.interior_eq, subset_compl_comm] - tfae_have 2 → 3 - · refine fun H a s => ⟨fun hd has => mem_closure_iff_nhds_ne_bot.mp has ?_, H s a⟩ + tfae_have 2 → 3 := by + refine fun H a s => ⟨fun hd has => mem_closure_iff_nhds_ne_bot.mp has ?_, H s a⟩ exact (hd.symm.mono_right <| @principal_le_nhdsSet _ _ s).eq_bot - tfae_have 3 → 1 - · exact fun H => ⟨fun hs ha => (H _ _).mpr <| hs.closure_eq.symm ▸ ha⟩ + tfae_have 3 → 1 := fun H => ⟨fun hs ha => (H _ _).mpr <| hs.closure_eq.symm ▸ ha⟩ tfae_finish theorem RegularSpace.of_lift'_closure_le (h : ∀ x : X, (𝓝 x).lift' closure ≤ 𝓝 x) : diff --git a/Mathlib/Topology/UniformSpace/UniformConvergence.lean b/Mathlib/Topology/UniformSpace/UniformConvergence.lean index b01801362aefe..4d216ca50a3ca 100644 --- a/Mathlib/Topology/UniformSpace/UniformConvergence.lean +++ b/Mathlib/Topology/UniformSpace/UniformConvergence.lean @@ -680,14 +680,14 @@ theorem tendstoLocallyUniformlyOn_TFAE [LocallyCompactSpace α] (G : ι → α ∀ K, K ⊆ s → IsCompact K → TendstoUniformlyOn G g p K, ∀ x ∈ s, ∃ v ∈ 𝓝[s] x, TendstoUniformlyOn G g p v] := by tfae_have 1 → 2 - · rintro h K hK1 hK2 - exact (tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK2).mp (h.mono hK1) + | h, K, hK1, hK2 => + (tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK2).mp (h.mono hK1) tfae_have 2 → 3 - · rintro h x hx + | h, x, hx => by obtain ⟨K, ⟨hK1, hK2⟩, hK3⟩ := (compact_basis_nhds x).mem_iff.mp (hs.mem_nhds hx) exact ⟨K, nhdsWithin_le_nhds hK1, h K hK3 hK2⟩ tfae_have 3 → 1 - · rintro h u hu x hx + | h, u, hu, x, hx => by obtain ⟨v, hv1, hv2⟩ := h x hx exact ⟨v, hv1, hv2 u hu⟩ tfae_finish From 87edf3cde7d03d590d10d3acc46cbc0d7a66f907 Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Tue, 24 Sep 2024 00:42:15 +0000 Subject: [PATCH 105/170] chore(Data/Finset): fix aesop finsetNonempty set (#16927) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All of these examples used `safe apply` for a rewrite lemma, and thus weren't actually used by `aesop` for finsetNonempty (and thus positivity). Co-authored-by: Yaël Dillies --- .../Algebra/Group/Pointwise/Finset/Basic.lean | 22 +++++++------- Mathlib/Data/Finset/Basic.lean | 21 +++++++++++--- Mathlib/Data/Finset/Image.lean | 6 ++-- Mathlib/Data/Finset/NAry.lean | 3 +- Mathlib/Data/Finset/Pi.lean | 5 +++- Mathlib/Data/Finset/Powerset.lean | 5 +++- Mathlib/Data/Finset/Prod.lean | 3 +- Mathlib/Data/Finset/Sigma.lean | 5 +++- Mathlib/Data/Finset/Sups.lean | 12 +++++--- Mathlib/Data/Finset/Sym.lean | 3 +- Mathlib/Data/Fintype/Basic.lean | 5 +++- Mathlib/Data/Fintype/Pi.lean | 5 +++- Mathlib/Order/Interval/Finset/Basic.lean | 29 +++++++++++++++---- 13 files changed, 90 insertions(+), 34 deletions(-) diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index 14f36bdd515fc..b36ab5a81b89b 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -210,12 +210,13 @@ theorem card_inv_le : s⁻¹.card ≤ s.card := theorem inv_empty : (∅ : Finset α)⁻¹ = ∅ := image_empty _ -@[to_additive (attr := simp, aesop safe apply (rule_sets := [finsetNonempty]))] +@[to_additive (attr := simp)] theorem inv_nonempty_iff : s⁻¹.Nonempty ↔ s.Nonempty := image_nonempty alias ⟨Nonempty.of_inv, Nonempty.inv⟩ := inv_nonempty_iff attribute [to_additive] Nonempty.inv Nonempty.of_inv +attribute [aesop safe apply (rule_sets := [finsetNonempty])] Nonempty.inv Nonempty.neg @[to_additive (attr := simp)] theorem inv_eq_empty : s⁻¹ = ∅ ↔ s = ∅ := image_eq_empty @@ -341,11 +342,11 @@ theorem mul_empty (s : Finset α) : s * ∅ = ∅ := theorem mul_eq_empty : s * t = ∅ ↔ s = ∅ ∨ t = ∅ := image₂_eq_empty_iff -@[to_additive (attr := simp, aesop safe apply (rule_sets := [finsetNonempty]))] +@[to_additive (attr := simp)] theorem mul_nonempty : (s * t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff -@[to_additive] +@[to_additive (attr := aesop safe apply (rule_sets := [finsetNonempty]))] theorem Nonempty.mul : s.Nonempty → t.Nonempty → (s * t).Nonempty := Nonempty.image₂ @@ -525,11 +526,11 @@ theorem div_empty (s : Finset α) : s / ∅ = ∅ := theorem div_eq_empty : s / t = ∅ ↔ s = ∅ ∨ t = ∅ := image₂_eq_empty_iff -@[to_additive (attr := simp, aesop safe apply (rule_sets := [finsetNonempty]))] +@[to_additive (attr := simp)] theorem div_nonempty : (s / t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff -@[to_additive] +@[to_additive (attr := aesop safe apply (rule_sets := [finsetNonempty]))] theorem Nonempty.div : s.Nonempty → t.Nonempty → (s / t).Nonempty := Nonempty.image₂ @@ -1119,11 +1120,11 @@ theorem smul_empty (s : Finset α) : s • (∅ : Finset β) = ∅ := theorem smul_eq_empty : s • t = ∅ ↔ s = ∅ ∨ t = ∅ := image₂_eq_empty_iff -@[to_additive (attr := simp, aesop safe apply (rule_sets := [finsetNonempty]))] +@[to_additive (attr := simp)] theorem smul_nonempty_iff : (s • t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff -@[to_additive] +@[to_additive (attr := aesop safe apply (rule_sets := [finsetNonempty]))] theorem Nonempty.smul : s.Nonempty → t.Nonempty → (s • t).Nonempty := Nonempty.image₂ @@ -1240,10 +1241,11 @@ theorem vsub_empty (s : Finset β) : s -ᵥ (∅ : Finset β) = ∅ := theorem vsub_eq_empty : s -ᵥ t = ∅ ↔ s = ∅ ∨ t = ∅ := image₂_eq_empty_iff -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem vsub_nonempty : (s -ᵥ t : Finset α).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff +@[aesop safe apply (rule_sets := [finsetNonempty])] theorem Nonempty.vsub : s.Nonempty → t.Nonempty → (s -ᵥ t : Finset α).Nonempty := Nonempty.image₂ @@ -1351,11 +1353,11 @@ theorem smul_finset_empty (a : α) : a • (∅ : Finset β) = ∅ := theorem smul_finset_eq_empty : a • s = ∅ ↔ s = ∅ := image_eq_empty -@[to_additive (attr := simp, aesop safe apply (rule_sets := [finsetNonempty]))] +@[to_additive (attr := simp)] theorem smul_finset_nonempty : (a • s).Nonempty ↔ s.Nonempty := image_nonempty -@[to_additive] +@[to_additive (attr := aesop safe apply (rule_sets := [finsetNonempty]))] theorem Nonempty.smul_finset (hs : s.Nonempty) : (a • s).Nonempty := hs.image _ diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index d979c5a475c1c..86d298bb40842 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -2093,10 +2093,11 @@ theorem mem_attach (s : Finset α) : ∀ x, x ∈ s.attach := theorem attach_empty : attach (∅ : Finset α) = ∅ := rfl -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem attach_nonempty_iff {s : Finset α} : s.attach.Nonempty ↔ s.Nonempty := by simp [Finset.Nonempty] +@[aesop safe apply (rule_sets := [finsetNonempty])] protected alias ⟨_, Nonempty.attach⟩ := attach_nonempty_iff @[simp] @@ -2574,15 +2575,19 @@ theorem mem_range_le {n x : ℕ} (hx : x ∈ range n) : x ≤ n := theorem mem_range_sub_ne_zero {n x : ℕ} (hx : x ∈ range n) : n - x ≠ 0 := _root_.ne_of_gt <| Nat.sub_pos_of_lt <| mem_range.1 hx -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem nonempty_range_iff : (range n).Nonempty ↔ n ≠ 0 := ⟨fun ⟨k, hk⟩ => (k.zero_le.trans_lt <| mem_range.1 hk).ne', fun h => ⟨0, mem_range.2 <| Nat.pos_iff_ne_zero.2 h⟩⟩ +@[aesop safe apply (rule_sets := [finsetNonempty])] +protected alias ⟨_, Aesop.range_nonempty⟩ := nonempty_range_iff + @[simp] theorem range_eq_empty_iff : range n = ∅ ↔ n = 0 := by rw [← not_nonempty_iff_eq_empty, nonempty_range_iff, not_not] +@[aesop safe apply (rule_sets := [finsetNonempty])] theorem nonempty_range_succ : (range <| n + 1).Nonempty := nonempty_range_iff.2 n.succ_ne_zero @@ -2722,10 +2727,13 @@ theorem toFinset_union (s t : Multiset α) : (s ∪ t).toFinset = s.toFinset ∪ theorem toFinset_eq_empty {m : Multiset α} : m.toFinset = ∅ ↔ m = 0 := Finset.val_inj.symm.trans Multiset.dedup_eq_zero -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem toFinset_nonempty : s.toFinset.Nonempty ↔ s ≠ 0 := by simp only [toFinset_eq_empty, Ne, Finset.nonempty_iff_ne_empty] +@[aesop safe apply (rule_sets := [finsetNonempty])] +protected alias ⟨_, Aesop.toFinset_nonempty_of_ne⟩ := toFinset_nonempty + @[simp] theorem toFinset_subset : s.toFinset ⊆ t.toFinset ↔ s ⊆ t := by simp only [Finset.subset_iff, Multiset.subset_iff, Multiset.mem_toFinset] @@ -2855,10 +2863,13 @@ theorem toFinset_inter (l l' : List α) : (l ∩ l').toFinset = l.toFinset ∩ l theorem toFinset_eq_empty_iff (l : List α) : l.toFinset = ∅ ↔ l = nil := by cases l <;> simp -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem toFinset_nonempty_iff (l : List α) : l.toFinset.Nonempty ↔ l ≠ [] := by simp [Finset.nonempty_iff_ne_empty] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.toFinset_nonempty_of_ne⟩ := toFinset_nonempty_iff + @[simp] theorem toFinset_filter (s : List α) (p : α → Bool) : (s.filter p).toFinset = s.toFinset.filter (p ·) := by @@ -3056,6 +3067,8 @@ You can add lemmas to the rule-set by tagging them with either: * `aesop safe apply (rule_sets := [finsetNonempty])` if they are always a good idea to follow or * `aesop unsafe apply (rule_sets := [finsetNonempty])` if they risk directing the search to a blind alley. + +TODO: should some of the lemmas be `aesop safe simp` instead? -/ def proveFinsetNonempty {u : Level} {α : Q(Type u)} (s : Q(Finset $α)) : MetaM (Option Q(Finset.Nonempty $s)) := do diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index 76bfac35dabe8..a571c2e8b4f10 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -242,10 +242,11 @@ theorem map_cons (f : α ↪ β) (a : α) (s : Finset α) (ha : a ∉ s) : @[simp] theorem map_eq_empty : s.map f = ∅ ↔ s = ∅ := (map_injective f).eq_iff' (map_empty f) -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem map_nonempty : (s.map f).Nonempty ↔ s.Nonempty := mod_cast Set.image_nonempty (f := f) (s := s) +@[aesop safe apply (rule_sets := [finsetNonempty])] protected alias ⟨_, Nonempty.map⟩ := map_nonempty @[simp] @@ -349,10 +350,11 @@ theorem _root_.Function.Injective.mem_finset_image (hf : Injective f) : theorem coe_image : ↑(s.image f) = f '' ↑s := Set.ext <| by simp only [mem_coe, mem_image, Set.mem_image, implies_true] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma image_nonempty : (s.image f).Nonempty ↔ s.Nonempty := mod_cast Set.image_nonempty (f := f) (s := (s : Set α)) +@[aesop safe apply (rule_sets := [finsetNonempty])] protected theorem Nonempty.image (h : s.Nonempty) (f : α → β) : (s.image f).Nonempty := image_nonempty.2 h diff --git a/Mathlib/Data/Finset/NAry.lean b/Mathlib/Data/Finset/NAry.lean index 74ad2d6a47ad7..fa32e7a832096 100644 --- a/Mathlib/Data/Finset/NAry.lean +++ b/Mathlib/Data/Finset/NAry.lean @@ -94,11 +94,12 @@ theorem image₂_subset_iff_left : image₂ f s t ⊆ u ↔ ∀ a ∈ s, (t.imag theorem image₂_subset_iff_right : image₂ f s t ⊆ u ↔ ∀ b ∈ t, (s.image fun a => f a b) ⊆ u := by simp_rw [image₂_subset_iff, image_subset_iff, @forall₂_swap α] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem image₂_nonempty_iff : (image₂ f s t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := by rw [← coe_nonempty, coe_image₂] exact image2_nonempty_iff +@[aesop safe apply (rule_sets := [finsetNonempty])] theorem Nonempty.image₂ (hs : s.Nonempty) (ht : t.Nonempty) : (image₂ f s t).Nonempty := image₂_nonempty_iff.2 ⟨hs, ht⟩ diff --git a/Mathlib/Data/Finset/Pi.lean b/Mathlib/Data/Finset/Pi.lean index 658eb02ed3164..8edf7868f430a 100644 --- a/Mathlib/Data/Finset/Pi.lean +++ b/Mathlib/Data/Finset/Pi.lean @@ -85,10 +85,13 @@ theorem Pi.cons_injective {a : α} {b : δ a} {s : Finset α} (hs : a ∉ s) : theorem pi_empty {t : ∀ a : α, Finset (β a)} : pi (∅ : Finset α) t = singleton (Pi.empty β) := rfl -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma pi_nonempty : (s.pi t).Nonempty ↔ ∀ a ∈ s, (t a).Nonempty := by simp [Finset.Nonempty, Classical.skolem] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, pi_nonempty_of_forall_nonempty⟩ := pi_nonempty + @[simp] theorem pi_insert [∀ a, DecidableEq (β a)] {s : Finset α} {t : ∀ a : α, Finset (β a)} {a : α} (ha : a ∉ s) : pi (insert a s) t = (t a).biUnion fun b => (pi s t).image (Pi.cons s a b) := by diff --git a/Mathlib/Data/Finset/Powerset.lean b/Mathlib/Data/Finset/Powerset.lean index ca7a34c9e0cbb..6e8275f105d31 100644 --- a/Mathlib/Data/Finset/Powerset.lean +++ b/Mathlib/Data/Finset/Powerset.lean @@ -234,10 +234,13 @@ theorem powersetCard_succ_insert [DecidableEq α] {x : α} {s : Finset α} (h : have : x ∉ t := fun H => h (ht H) simp [card_insert_of_not_mem this, Nat.succ_inj'] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma powersetCard_nonempty : (powersetCard n s).Nonempty ↔ n ≤ s.card := by aesop (add simp [Finset.Nonempty, exists_subset_card_eq, card_le_card]) +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, powersetCard_nonempty_of_le⟩ := powersetCard_nonempty + @[simp] theorem powersetCard_self (s : Finset α) : powersetCard s.card s = {s} := by ext diff --git a/Mathlib/Data/Finset/Prod.lean b/Mathlib/Data/Finset/Prod.lean index b0304921a947b..5af6d692ec6e5 100644 --- a/Mathlib/Data/Finset/Prod.lean +++ b/Mathlib/Data/Finset/Prod.lean @@ -168,6 +168,7 @@ theorem empty_product (t : Finset β) : (∅ : Finset α) ×ˢ t = ∅ := theorem product_empty (s : Finset α) : s ×ˢ (∅ : Finset β) = ∅ := eq_empty_of_forall_not_mem fun _ h => not_mem_empty _ (Finset.mem_product.1 h).2 +@[aesop safe apply (rule_sets := [finsetNonempty])] theorem Nonempty.product (hs : s.Nonempty) (ht : t.Nonempty) : (s ×ˢ t).Nonempty := let ⟨x, hx⟩ := hs let ⟨y, hy⟩ := ht @@ -181,7 +182,7 @@ theorem Nonempty.snd (h : (s ×ˢ t).Nonempty) : t.Nonempty := let ⟨xy, hxy⟩ := h ⟨xy.2, (mem_product.1 hxy).2⟩ -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem nonempty_product : (s ×ˢ t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := ⟨fun h => ⟨h.fst, h.snd⟩, fun h => h.1.product h.2⟩ diff --git a/Mathlib/Data/Finset/Sigma.lean b/Mathlib/Data/Finset/Sigma.lean index 5be327d9e74de..e3f0b82144225 100644 --- a/Mathlib/Data/Finset/Sigma.lean +++ b/Mathlib/Data/Finset/Sigma.lean @@ -51,9 +51,12 @@ theorem coe_sigma (s : Finset ι) (t : ∀ i, Finset (α i)) : (s.sigma t : Set (Σ i, α i)) = (s : Set ι).sigma fun i ↦ (t i : Set (α i)) := Set.ext fun _ => mem_sigma -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem sigma_nonempty : (s.sigma t).Nonempty ↔ ∃ i ∈ s, (t i).Nonempty := by simp [Finset.Nonempty] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.sigma_nonempty_of_exists_nonempty⟩ := sigma_nonempty + @[simp] theorem sigma_eq_empty : s.sigma t = ∅ ↔ ∀ i ∈ s, t i = ∅ := by simp only [← not_nonempty_iff_eq_empty, sigma_nonempty, not_exists, not_and] diff --git a/Mathlib/Data/Finset/Sups.lean b/Mathlib/Data/Finset/Sups.lean index db0f05061163e..16e426c59c332 100644 --- a/Mathlib/Data/Finset/Sups.lean +++ b/Mathlib/Data/Finset/Sups.lean @@ -99,10 +99,11 @@ theorem forall_sups_iff {p : α → Prop} : (∀ c ∈ s ⊻ t, p c) ↔ ∀ a theorem sups_subset_iff : s ⊻ t ⊆ u ↔ ∀ a ∈ s, ∀ b ∈ t, a ⊔ b ∈ u := image₂_subset_iff -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem sups_nonempty : (s ⊻ t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff +@[aesop safe apply (rule_sets := [finsetNonempty])] protected theorem Nonempty.sups : s.Nonempty → t.Nonempty → (s ⊻ t).Nonempty := Nonempty.image₂ @@ -245,10 +246,11 @@ theorem forall_infs_iff {p : α → Prop} : (∀ c ∈ s ⊼ t, p c) ↔ ∀ a theorem infs_subset_iff : s ⊼ t ⊆ u ↔ ∀ a ∈ s, ∀ b ∈ t, a ⊓ b ∈ u := image₂_subset_iff -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem infs_nonempty : (s ⊼ t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff +@[aesop safe apply (rule_sets := [finsetNonempty])] protected theorem Nonempty.infs : s.Nonempty → t.Nonempty → (s ⊼ t).Nonempty := Nonempty.image₂ @@ -555,9 +557,10 @@ lemma forall_mem_diffs {p : α → Prop} : (∀ c ∈ s \\ t, p c) ↔ ∀ a ∈ @[simp] lemma diffs_subset_iff : s \\ t ⊆ u ↔ ∀ a ∈ s, ∀ b ∈ t, a \ b ∈ u := image₂_subset_iff -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma diffs_nonempty : (s \\ t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := image₂_nonempty_iff +@[aesop safe apply (rule_sets := [finsetNonempty])] protected lemma Nonempty.diffs : s.Nonempty → t.Nonempty → (s \\ t).Nonempty := Nonempty.image₂ lemma Nonempty.of_diffs_left : (s \\ t).Nonempty → s.Nonempty := Nonempty.of_image₂_left @@ -629,10 +632,11 @@ lemma exists_compls_iff {p : α → Prop} : (∃ a ∈ sᶜˢ, p a) ↔ ∃ a lemma compls_subset_iff : sᶜˢ ⊆ t ↔ s ⊆ tᶜˢ := by rw [← compls_subset_compls, compls_compls] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma compls_nonempty : sᶜˢ.Nonempty ↔ s.Nonempty := map_nonempty protected alias ⟨Nonempty.of_compls, Nonempty.compls⟩ := compls_nonempty +attribute [aesop safe apply (rule_sets := [finsetNonempty])] Nonempty.compls @[simp] lemma compls_empty : (∅ : Finset α)ᶜˢ = ∅ := map_empty _ @[simp] lemma compls_eq_empty : sᶜˢ = ∅ ↔ s = ∅ := map_eq_empty diff --git a/Mathlib/Data/Finset/Sym.lean b/Mathlib/Data/Finset/Sym.lean index 951449e44c9db..c591056cea7ff 100644 --- a/Mathlib/Data/Finset/Sym.lean +++ b/Mathlib/Data/Finset/Sym.lean @@ -109,11 +109,12 @@ theorem sym2_empty : (∅ : Finset α).sym2 = ∅ := rfl theorem sym2_eq_empty : s.sym2 = ∅ ↔ s = ∅ := by rw [← val_eq_zero, sym2_val, Multiset.sym2_eq_zero_iff, val_eq_zero] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem sym2_nonempty : s.sym2.Nonempty ↔ s.Nonempty := by rw [← not_iff_not] simp_rw [not_nonempty_iff_eq_empty, sym2_eq_empty] +@[aesop safe apply (rule_sets := [finsetNonempty])] protected alias ⟨_, Nonempty.sym2⟩ := sym2_nonempty @[simp] diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 065dfecfbeb4e..e18eca0fb06df 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -621,10 +621,13 @@ def decidableMemOfFintype [DecidableEq α] (s : Set α) [Fintype s] (a) : Decida theorem coe_toFinset (s : Set α) [Fintype s] : (↑s.toFinset : Set α) = s := Set.ext fun _ => mem_toFinset -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem toFinset_nonempty {s : Set α} [Fintype s] : s.toFinset.Nonempty ↔ s.Nonempty := by rw [← Finset.coe_nonempty, coe_toFinset] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.toFinset_nonempty_of_nonempty⟩ := toFinset_nonempty + @[simp] theorem toFinset_inj {s t : Set α} [Fintype s] [Fintype t] : s.toFinset = t.toFinset ↔ s = t := ⟨fun h => by rw [← s.coe_toFinset, h, t.coe_toFinset], fun h => by simp [h]⟩ diff --git a/Mathlib/Data/Fintype/Pi.lean b/Mathlib/Data/Fintype/Pi.lean index a216886258a7e..8b57b9e376500 100644 --- a/Mathlib/Data/Fintype/Pi.lean +++ b/Mathlib/Data/Fintype/Pi.lean @@ -52,10 +52,13 @@ theorem piFinset_subset (t₁ t₂ : ∀ a, Finset (δ a)) (h : ∀ a, t₁ a theorem piFinset_empty [Nonempty α] : piFinset (fun _ => ∅ : ∀ i, Finset (δ i)) = ∅ := eq_empty_of_forall_not_mem fun _ => by simp -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma piFinset_nonempty : (piFinset s).Nonempty ↔ ∀ a, (s a).Nonempty := by simp [Finset.Nonempty, Classical.skolem] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.piFinset_nonempty_of_forall_nonempty⟩ := piFinset_nonempty + lemma _root_.Finset.Nonempty.piFinset_const {ι : Type*} [Fintype ι] [DecidableEq ι] {s : Finset β} (hs : s.Nonempty) : (piFinset fun _ : ι ↦ s).Nonempty := piFinset_nonempty.2 fun _ ↦ hs diff --git a/Mathlib/Order/Interval/Finset/Basic.lean b/Mathlib/Order/Interval/Finset/Basic.lean index f47de398e6c28..baa9a5f67300a 100644 --- a/Mathlib/Order/Interval/Finset/Basic.lean +++ b/Mathlib/Order/Interval/Finset/Basic.lean @@ -51,18 +51,27 @@ section LocallyFiniteOrder variable [LocallyFiniteOrder α] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] theorem nonempty_Icc : (Icc a b).Nonempty ↔ a ≤ b := by rw [← coe_nonempty, coe_Icc, Set.nonempty_Icc] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.nonempty_Icc_of_le⟩ := nonempty_Icc + +@[simp] theorem nonempty_Ico : (Ico a b).Nonempty ↔ a < b := by rw [← coe_nonempty, coe_Ico, Set.nonempty_Ico] -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.nonempty_Ico_of_lt⟩ := nonempty_Ico + +@[simp] theorem nonempty_Ioc : (Ioc a b).Nonempty ↔ a < b := by rw [← coe_nonempty, coe_Ioc, Set.nonempty_Ioc] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.nonempty_Ioc_of_lt⟩ := nonempty_Ioc + -- TODO: This is nonsense. A locally finite order is never densely ordered @[simp] theorem nonempty_Ioo [DenselyOrdered α] : (Ioo a b).Nonempty ↔ a < b := by @@ -331,9 +340,12 @@ variable [LocallyFiniteOrderTop α] @[simp, aesop safe apply (rule_sets := [finsetNonempty])] lemma nonempty_Ici : (Ici a).Nonempty := ⟨a, mem_Ici.2 le_rfl⟩ -@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +@[simp] lemma nonempty_Ioi : (Ioi a).Nonempty ↔ ¬ IsMax a := by simp [Finset.Nonempty] +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.nonempty_Ioi_of_not_isMax⟩ := nonempty_Ioi + theorem Ici_subset_Ici : Ici a ⊆ Ici b ↔ b ≤ a := by simpa [← coe_subset] using Set.Ici_subset_Ici @@ -366,8 +378,13 @@ section LocallyFiniteOrderBot variable [LocallyFiniteOrderBot α] -@[simp] lemma nonempty_Iic : (Iic a).Nonempty := ⟨a, mem_Iic.2 le_rfl⟩ -@[simp] lemma nonempty_Iio : (Iio a).Nonempty ↔ ¬ IsMin a := by simp [Finset.Nonempty] +@[simp, aesop safe apply (rule_sets := [finsetNonempty])] +lemma nonempty_Iic : (Iic a).Nonempty := ⟨a, mem_Iic.2 le_rfl⟩ +@[simp] +lemma nonempty_Iio : (Iio a).Nonempty ↔ ¬ IsMin a := by simp [Finset.Nonempty] + +@[aesop safe apply (rule_sets := [finsetNonempty])] +alias ⟨_, Aesop.nonempty_Iio_of_not_isMin⟩ := nonempty_Iio theorem Iic_subset_Iic : Iic a ⊆ Iic b ↔ a ≤ b := by simpa [← coe_subset] using Set.Iic_subset_Iic From 97987b259b30de67e76d7bb607973d49fd446768 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 24 Sep 2024 00:42:16 +0000 Subject: [PATCH 106/170] chore(UniqueFactorizationDomain): drop `pow_right_injective` (#17012) Use more general lemmas instead --- Mathlib/Algebra/Associated/Basic.lean | 9 ++++++++- Mathlib/RingTheory/ChainOfDivisors.lean | 2 +- Mathlib/RingTheory/DedekindDomain/Ideal.lean | 2 +- .../RingTheory/UniqueFactorizationDomain.lean | 16 ++-------------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Mathlib/Algebra/Associated/Basic.lean b/Mathlib/Algebra/Associated/Basic.lean index 70a806de2380a..7eaa44c44512d 100644 --- a/Mathlib/Algebra/Associated/Basic.lean +++ b/Mathlib/Algebra/Associated/Basic.lean @@ -1124,12 +1124,19 @@ theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p rw [(mul_left_cancel₀ hp hx'').symm] at hx' exact hx' isUnit_one -theorem pow_injective_of_not_unit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q) +theorem pow_injective_of_not_isUnit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q) (hq' : q ≠ 0) : Function.Injective fun n : ℕ => q ^ n := by refine injective_of_lt_imp_ne fun n m h => DvdNotUnit.ne ⟨pow_ne_zero n hq', q ^ (m - n), ?_, ?_⟩ · exact not_isUnit_of_not_isUnit_dvd hq (dvd_pow (dvd_refl _) (Nat.sub_pos_of_lt h).ne') · exact (pow_mul_pow_sub q h.le).symm +@[deprecated (since := "2024-09-22")] +alias pow_injective_of_not_unit := pow_injective_of_not_isUnit + +theorem pow_inj_of_not_isUnit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q) + (hq' : q ≠ 0) {m n : ℕ} : q ^ m = q ^ n ↔ m = n := + (pow_injective_of_not_isUnit hq hq').eq_iff + theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) : q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by induction n generalizing q with diff --git a/Mathlib/RingTheory/ChainOfDivisors.lean b/Mathlib/RingTheory/ChainOfDivisors.lean index ed816bb3683ea..8266ff382b37f 100644 --- a/Mathlib/RingTheory/ChainOfDivisors.lean +++ b/Mathlib/RingTheory/ChainOfDivisors.lean @@ -160,7 +160,7 @@ theorem element_of_chain_eq_pow_second_of_chain {q r : Associates M} {n : ℕ} ( rw [Finset.card_image_iff] refine Set.injOn_of_injective (fun m m' h => Fin.ext ?_) refine - pow_injective_of_not_unit (element_of_chain_not_isUnit_of_index_ne_zero (by simp) h₁) ?_ h + pow_injective_of_not_isUnit (element_of_chain_not_isUnit_of_index_ne_zero (by simp) h₁) ?_ h exact Irreducible.ne_zero (second_of_chain_is_irreducible hn h₁ (@h₂) hq) suffices H' : ∀ r ∈ Finset.univ.image fun m : Fin (i + 1) => c 1 ^ (m : ℕ), r ≤ q by simp only [← Nat.succ_le_iff, Nat.succ_eq_add_one, ← this] diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 798b6e6abf371..788005c401860 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -720,7 +720,7 @@ theorem Ideal.eq_prime_pow_of_succ_lt_of_le {P I : Ideal A} [P_prime : P.IsPrime theorem Ideal.pow_succ_lt_pow {P : Ideal A} [P_prime : P.IsPrime] (hP : P ≠ ⊥) (i : ℕ) : P ^ (i + 1) < P ^ i := lt_of_le_of_ne (Ideal.pow_le_pow_right (Nat.le_succ _)) - (mt (pow_eq_pow_iff hP (mt Ideal.isUnit_iff.mp P_prime.ne_top)).mp i.succ_ne_self) + (mt (pow_inj_of_not_isUnit (mt Ideal.isUnit_iff.mp P_prime.ne_top) hP).mp i.succ_ne_self) theorem Associates.le_singleton_iff (x : A) (n : ℕ) (I : Ideal A) : Associates.mk I ^ n ≤ Associates.mk (Ideal.span {x}) ↔ x ∈ I ^ n := by diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain.lean b/Mathlib/RingTheory/UniqueFactorizationDomain.lean index 619ab4c415bcb..edce0ce9c8677 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain.lean @@ -912,20 +912,8 @@ theorem exists_reduced_factors' (a b : R) (hb : b ≠ 0) : let ⟨b', a', c', no_factor, hb, ha⟩ := exists_reduced_factors b hb a ⟨a', b', c', fun _ hpb hpa => no_factor hpa hpb, ha, hb⟩ -theorem pow_right_injective {a : R} (ha0 : a ≠ 0) (ha1 : ¬IsUnit a) : - Function.Injective (a ^ · : ℕ → R) := by - letI := Classical.decEq R - intro i j hij - letI : Nontrivial R := ⟨⟨a, 0, ha0⟩⟩ - letI : NormalizationMonoid R := UniqueFactorizationMonoid.normalizationMonoid - obtain ⟨p', hp', dvd'⟩ := WfDvdMonoid.exists_irreducible_factor ha1 ha0 - obtain ⟨p, mem, _⟩ := exists_mem_normalizedFactors_of_dvd ha0 hp' dvd' - have := congr_arg (fun x => Multiset.count p (normalizedFactors x)) hij - simp only [normalizedFactors_pow, Multiset.count_nsmul] at this - exact mul_right_cancel₀ (Multiset.count_ne_zero.mpr mem) this - -theorem pow_eq_pow_iff {a : R} (ha0 : a ≠ 0) (ha1 : ¬IsUnit a) {i j : ℕ} : a ^ i = a ^ j ↔ i = j := - (pow_right_injective ha0 ha1).eq_iff +@[deprecated (since := "2024-09-21")] alias pow_right_injective := pow_injective_of_not_isUnit +@[deprecated (since := "2024-09-21")] alias pow_eq_pow_iff := pow_inj_of_not_isUnit section multiplicity From fd587965db77dd971e90f7d1861a2863b1b6c367 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 24 Sep 2024 00:42:18 +0000 Subject: [PATCH 107/170] feat: semi-uniqueness of limits in seminormed spaces (#17066) [Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/Tendsto.20in.20seminormed.20spaces/near/472351143) --- Mathlib/Topology/EMetricSpace/Basic.lean | 2 ++ Mathlib/Topology/MetricSpace/Pseudo/Basic.lean | 14 +++++++++++++- Mathlib/Topology/Separation.lean | 15 +++++++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Mathlib/Topology/EMetricSpace/Basic.lean b/Mathlib/Topology/EMetricSpace/Basic.lean index 6dba286e22d97..20efe03e7d47a 100644 --- a/Mathlib/Topology/EMetricSpace/Basic.lean +++ b/Mathlib/Topology/EMetricSpace/Basic.lean @@ -144,6 +144,8 @@ variable {x y z : α} {ε ε₁ ε₂ : ℝ≥0∞} {s t : Set α} theorem inseparable_iff : Inseparable x y ↔ edist x y = 0 := by simp [inseparable_iff_mem_closure, mem_closure_iff, edist_comm, forall_lt_iff_le'] +alias ⟨_root_.Inseparable.edist_eq_zero, _⟩ := EMetric.inseparable_iff + -- see Note [nolint_ge] /-- In a pseudoemetric space, Cauchy sequences are characterized by the fact that, eventually, the pseudoedistance between its elements is arbitrarily small -/ diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean b/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean index 5793a4509ed7c..65722ebb2e6b9 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean @@ -169,8 +169,20 @@ end Metric open Metric +theorem Metric.inseparable_iff_nndist {x y : α} : Inseparable x y ↔ nndist x y = 0 := by + rw [EMetric.inseparable_iff, edist_nndist, ENNReal.coe_eq_zero] + +alias ⟨Inseparable.nndist_eq_zero, _⟩ := Metric.inseparable_iff_nndist + theorem Metric.inseparable_iff {x y : α} : Inseparable x y ↔ dist x y = 0 := by - rw [EMetric.inseparable_iff, edist_nndist, dist_nndist, ENNReal.coe_eq_zero, NNReal.coe_eq_zero] + rw [Metric.inseparable_iff_nndist, dist_nndist, NNReal.coe_eq_zero] + +alias ⟨Inseparable.dist_eq_zero, _⟩ := Metric.inseparable_iff + +/-- A weaker version of `tendsto_nhds_unique` for `PseudoMetricSpace`. -/ +theorem tendsto_nhds_unique_dist {f : β → α} {l : Filter β} {x y : α} [NeBot l] + (ha : Tendsto f l (𝓝 x)) (hb : Tendsto f l (𝓝 y)) : dist x y = 0 := + (tendsto_nhds_unique_inseparable ha hb).dist_eq_zero section Real diff --git a/Mathlib/Topology/Separation.lean b/Mathlib/Topology/Separation.lean index 500bae87ab25c..2f7f8cfdcd660 100644 --- a/Mathlib/Topology/Separation.lean +++ b/Mathlib/Topology/Separation.lean @@ -1043,6 +1043,17 @@ theorem r1Space_iff_inseparable_or_disjoint_nhds {X : Type*} [TopologicalSpace X ⟨fun _h x y ↦ (specializes_or_disjoint_nhds x y).imp_left Specializes.inseparable, fun h ↦ ⟨fun x y ↦ (h x y).imp_left Inseparable.specializes⟩⟩ +theorem Inseparable.of_nhds_neBot {x y : X} (h : NeBot (𝓝 x ⊓ 𝓝 y)) : + Inseparable x y := + (r1Space_iff_inseparable_or_disjoint_nhds.mp ‹_› _ _).resolve_right fun h' => h.ne h'.eq_bot + +/-- Limits are unique up to separability. + +A weaker version of `tendsto_nhds_unique` for `R1Space`. -/ +theorem tendsto_nhds_unique_inseparable {f : Y → X} {l : Filter Y} {a b : X} [NeBot l] + (ha : Tendsto f l (𝓝 a)) (hb : Tendsto f l (𝓝 b)) : Inseparable a b := + .of_nhds_neBot <| neBot_of_le <| le_inf ha hb + theorem isClosed_setOf_specializes : IsClosed { p : X × X | p.1 ⤳ p.2 } := by simp only [← isOpen_compl_iff, compl_setOf, ← disjoint_nhds_nhds_iff_not_specializes, isOpen_setOf_disjoint_nhds_nhds] @@ -1380,11 +1391,11 @@ theorem isClosed_diagonal [T2Space X] : IsClosed (diagonal X) := theorem tendsto_nhds_unique [T2Space X] {f : Y → X} {l : Filter Y} {a b : X} [NeBot l] (ha : Tendsto f l (𝓝 a)) (hb : Tendsto f l (𝓝 b)) : a = b := - eq_of_nhds_neBot <| neBot_of_le <| le_inf ha hb + (tendsto_nhds_unique_inseparable ha hb).eq theorem tendsto_nhds_unique' [T2Space X] {f : Y → X} {l : Filter Y} {a b : X} (_ : NeBot l) (ha : Tendsto f l (𝓝 a)) (hb : Tendsto f l (𝓝 b)) : a = b := - eq_of_nhds_neBot <| neBot_of_le <| le_inf ha hb + tendsto_nhds_unique ha hb theorem tendsto_nhds_unique_of_eventuallyEq [T2Space X] {f g : Y → X} {l : Filter Y} {a b : X} [NeBot l] (ha : Tendsto f l (𝓝 a)) (hb : Tendsto g l (𝓝 b)) (hfg : f =ᶠ[l] g) : a = b := From 2ba4ba37a789b3da870d0dd8ee4d92fba6292f97 Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 24 Sep 2024 01:34:19 +0000 Subject: [PATCH 108/170] fix: remove self-cancelling `set_option ... in` (#17054) While possibly confusing, `set_option ... in section` does not extend past `section`. --- Mathlib/Algebra/Ring/Parity.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/Algebra/Ring/Parity.lean b/Mathlib/Algebra/Ring/Parity.lean index 94a1d21b3a889..8d540524abfb4 100644 --- a/Mathlib/Algebra/Ring/Parity.lean +++ b/Mathlib/Algebra/Ring/Parity.lean @@ -324,7 +324,6 @@ namespace Involutive variable {α : Type*} {f : α → α} {n : ℕ} -set_option linter.deprecated false in section lemma iterate_bit0 (hf : Involutive f) (n : ℕ) : f^[2 * n] = id := by From 7fdf3ba6cd0ac00e60a4a2add95240ed987f8ec5 Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Tue, 24 Sep 2024 01:34:20 +0000 Subject: [PATCH 109/170] chore: remove non-ascii whitespace (#17068) Preliminary cleanup for the "unwanted unicode linter" added in #16215. --- Mathlib/CategoryTheory/Adjunction/Opposites.lean | 4 ++-- Mathlib/CategoryTheory/Adjunction/Triple.lean | 4 ++-- Mathlib/CategoryTheory/Closed/Monoidal.lean | 4 ++-- Mathlib/CategoryTheory/Sites/ConstantSheaf.lean | 6 +++--- Mathlib/Logic/Function/FiberPartition.lean | 8 ++++---- .../Topology/Category/CompHausLike/Basic.lean | 14 +++++++------- .../Category/CompHausLike/SigmaComparison.lean | 4 ++-- .../Topology/Category/LightProfinite/Extend.lean | 16 ++++++++-------- Mathlib/Topology/Category/Profinite/Extend.lean | 16 ++++++++-------- 9 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Mathlib/CategoryTheory/Adjunction/Opposites.lean b/Mathlib/CategoryTheory/Adjunction/Opposites.lean index ebf024b209026..f4362585c27a4 100644 --- a/Mathlib/CategoryTheory/Adjunction/Opposites.lean +++ b/Mathlib/CategoryTheory/Adjunction/Opposites.lean @@ -36,13 +36,13 @@ def adjointOfOpAdjointOp (F : C ⥤ D) (G : D ⥤ C) (h : G.op ⊣ F.op) : F ⊣ (opEquiv _ _) homEquiv_naturality_left_symm := by -- Porting note: This proof was handled by `obviously` in mathlib3. The only obstruction to - -- automation fully kicking in here is that the `@[simps]` lemmas of `opEquiv` and + -- automation fully kicking in here is that the `@[simps]` lemmas of `opEquiv` and -- `homEquiv` aren't firing. intros simp [opEquiv, homEquiv] homEquiv_naturality_right := by -- Porting note: This proof was handled by `obviously` in mathlib3. The only obstruction to - -- automation fully kicking in here is that the `@[simps]` lemmas of `opEquiv` and + -- automation fully kicking in here is that the `@[simps]` lemmas of `opEquiv` and -- `homEquiv` aren't firing. intros simp [opEquiv, homEquiv] } diff --git a/Mathlib/CategoryTheory/Adjunction/Triple.lean b/Mathlib/CategoryTheory/Adjunction/Triple.lean index d8b28fd060834..d1ee7a410b19f 100644 --- a/Mathlib/CategoryTheory/Adjunction/Triple.lean +++ b/Mathlib/CategoryTheory/Adjunction/Triple.lean @@ -11,7 +11,7 @@ import Mathlib.CategoryTheory.Monad.Adjunction This file concerns adjoint triples `F ⊣ G ⊣ H` of functors `F H : C ⥤ D`, `G : D ⥤ C`. -Currently, the only result is that `F` is fully faithful if and only if `H` is fully faithful. +Currently, the only result is that `F` is fully faithful if and only if `H` is fully faithful. -/ namespace CategoryTheory.Adjunction @@ -31,7 +31,7 @@ lemma isIso_unit_iff_isIso_counit : IsIso adj₁.unit ↔ IsIso adj₂.counit := exact adj₁.isIso_unit_of_iso (adjId.leftAdjointUniq id) /-- -Given an adjoint triple `F ⊣ G ⊣ H`, the left adjoint `F` is fully faithful if and only if the +Given an adjoint triple `F ⊣ G ⊣ H`, the left adjoint `F` is fully faithful if and only if the right adjoint `H` is fully faithful. -/ noncomputable def fullyFaithfulEquiv : F.FullyFaithful ≃ H.FullyFaithful where diff --git a/Mathlib/CategoryTheory/Closed/Monoidal.lean b/Mathlib/CategoryTheory/Closed/Monoidal.lean index ee743bbcdc148..5a32bc0ce83e8 100644 --- a/Mathlib/CategoryTheory/Closed/Monoidal.lean +++ b/Mathlib/CategoryTheory/Closed/Monoidal.lean @@ -267,7 +267,7 @@ theorem ofEquiv_curry_def {X Y Z : C} (f : X ⊗ Y ⟶ Z) : (MonoidalClosed.curry (adj.toEquivalence.symm.toAdjunction.homEquiv (F.obj X ⊗ F.obj Y) Z ((Iso.compInverseIso (H := adj.toEquivalence) (MonoidalFunctor.commTensorLeft F X)).hom.app Y ≫ f))) := by - -- This whole proof used to be `rfl` before #16317. + -- This whole proof used to be `rfl` before #16317. change ((adj.comp ((ihom.adjunction (F.obj X)).comp adj.toEquivalence.symm.toAdjunction)).ofNatIsoLeft _).homEquiv _ _ _ = _ dsimp only [Adjunction.ofNatIsoLeft] @@ -289,7 +289,7 @@ theorem ofEquiv_uncurry_def {X Y Z : C} : (adj.toEquivalence.symm.toAdjunction.homEquiv _ _).symm (MonoidalClosed.uncurry ((adj.homEquiv _ _).symm f)) := by intro f - -- This whole proof used to be `rfl` before #16317. + -- This whole proof used to be `rfl` before #16317. change (((adj.comp ((ihom.adjunction (F.obj X)).comp adj.toEquivalence.symm.toAdjunction)).ofNatIsoLeft _).homEquiv _ _).symm _ = _ dsimp only [Adjunction.ofNatIsoLeft] diff --git a/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean b/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean index 0786da4e1318e..46db78d658c1f 100644 --- a/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean +++ b/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean @@ -25,7 +25,7 @@ it is an isomorphism. * `Sheaf.isConstant_iff_of_equivalence` : The property of a sheaf of being constant is invariant under equivalence of sheaf categories. -* `Sheaf.isConstant_iff_forget` : Given a "forgetful" functor `U : D ⥤ B` a sheaf `F : Sheaf J D` is +* `Sheaf.isConstant_iff_forget` : Given a "forgetful" functor `U : D ⥤ B` a sheaf `F : Sheaf J D` is constant if and only if the sheaf given by postcomposition with `U` is constant. ## Future work @@ -177,7 +177,7 @@ variable {B : Type*} [Category B] (U : D ⥤ B) [HasWeakSheafify J B] [J.PreservesSheafification U] [J.HasSheafCompose U] (F : Sheaf J D) /-- -The constant sheaf functor commutes with `sheafCompose J U` up to isomorphism, provided that `U`  +The constant sheaf functor commutes with `sheafCompose J U` up to isomorphism, provided that `U` preserves sheafification. -/ noncomputable def constantCommuteCompose : @@ -189,7 +189,7 @@ noncomputable def constantCommuteCompose : lemma constantCommuteCompose_hom_app_val (X : D) : ((constantCommuteCompose J U).hom.app X).val = (sheafifyComposeIso J U ((const Cᵒᵖ).obj X)).inv ≫ sheafifyMap J (constComp Cᵒᵖ X U).hom := rfl -/-- The counit of `constantSheafAdj` factors through the isomorphism `constantCommuteCompose`. -/ +/-- The counit of `constantSheafAdj` factors through the isomorphism `constantCommuteCompose`. -/ lemma constantSheafAdj_counit_w {T : C} (hT : IsTerminal T) : ((constantCommuteCompose J U).hom.app (F.val.obj ⟨T⟩)) ≫ ((constantSheafAdj J B hT).counit.app ((sheafCompose J U).obj F)) = diff --git a/Mathlib/Logic/Function/FiberPartition.lean b/Mathlib/Logic/Function/FiberPartition.lean index c9d2f8a334e71..e82895e5b975f 100644 --- a/Mathlib/Logic/Function/FiberPartition.lean +++ b/Mathlib/Logic/Function/FiberPartition.lean @@ -6,7 +6,7 @@ Authors: Dagur Asgeirsson import Mathlib.Data.Set.Basic /-! -This file defines the type `f.Fiber` of fibers of a function `f : Y → Z`, and provides some API +This file defines the type `f.Fiber` of fibers of a function `f : Y → Z`, and provides some API to work with and construct terms of this type. Note: this API is designed to be useful when defining the counit of the adjunction between @@ -25,7 +25,7 @@ def Fiber (f : Y → Z) : Type _ := Set.range (fun (x : Set.range f) ↦ f ⁻¹ namespace Fiber /-- -Any `a : Fiber f` is of the form `f ⁻¹' {x}` for some `x` in the image of `f`. We define `a.image`  +Any `a : Fiber f` is of the form `f ⁻¹' {x}` for some `x` in the image of `f`. We define `a.image` as an arbitrary such `x`. -/ noncomputable def image (f : Y → Z) (a : Fiber f) : Z := a.2.choose.1 @@ -33,11 +33,11 @@ noncomputable def image (f : Y → Z) (a : Fiber f) : Z := a.2.choose.1 lemma eq_fiber_image (f : Y → Z) (a : Fiber f) : a.1 = f ⁻¹' {a.image} := a.2.choose_spec.symm /-- -Given `y : Y`, `Fiber.mk f y` is the fiber of `f` that `y` belongs to, as an element of `Fiber f`. +Given `y : Y`, `Fiber.mk f y` is the fiber of `f` that `y` belongs to, as an element of `Fiber f`. -/ def mk (f : Y → Z) (y : Y) : Fiber f := ⟨f ⁻¹' {f y}, by simp⟩ -/-- `y : Y` as a term of the type `Fiber.mk f y` -/ +/-- `y : Y` as a term of the type `Fiber.mk f y` -/ def mkSelf (f : Y → Z) (y : Y) : (mk f y).val := ⟨y, rfl⟩ lemma map_eq_image (f : Y → Z) (a : Fiber f) (x : a.1) : f x = a.image := by diff --git a/Mathlib/Topology/Category/CompHausLike/Basic.lean b/Mathlib/Topology/Category/CompHausLike/Basic.lean index 62495d9004dfa..045cd7441ef88 100644 --- a/Mathlib/Topology/Category/CompHausLike/Basic.lean +++ b/Mathlib/Topology/Category/CompHausLike/Basic.lean @@ -13,21 +13,21 @@ We construct the category of compact Hausdorff spaces satisfying an additional p ## Implementation -We define a structure `CompHausLike` which takes as an argument a predicate `P` on topological +We define a structure `CompHausLike` which takes as an argument a predicate `P` on topological spaces. It consists of the data of a topological space, satisfying the additional properties of being compact and Hausdorff, and satisfying `P`. We give a category structure to `CompHausLike P` induced by the forgetful functor to topological spaces. It used to be the case (before #12930 was merged) that several different categories of compact Hausdorff spaces, possibly satisfying some extra property, were defined from scratch in this way. -For example, one would define a structure `CompHaus` as follows: +For example, one would define a structure `CompHaus` as follows: ```lean structure CompHaus where toTop : TopCat [is_compact : CompactSpace toTop] [is_hausdorff : T2Space toTop] -```  +``` and give it the category structure induced from topological spaces. Then the category of profinite spaces was defined as follows: @@ -39,7 +39,7 @@ structure Profinite where ``` The categories `Stonean` consisting of extremally disconnected compact Hausdorff spaces and -`LightProfinite` consisting of totally disconnected, second countable compact Hausdorff spaces were +`LightProfinite` consisting of totally disconnected, second countable compact Hausdorff spaces were defined in a similar way. This resulted in code duplication, and reducing this duplication was part of the motivation for introducing `CompHausLike`. @@ -52,11 +52,11 @@ Using `CompHausLike`, we can now define These four categories are important building blocks of condensed objects (see the files `Condensed.Basic` and `Condensed.Light.Basic`). These categories share many properties and often, one wants to argue about several of them simultaneously. This is the other part of the motivation -for introducing `CompHausLike`. On paper, one would say "let `C` be on of the categories `CompHaus` +for introducing `CompHausLike`. On paper, one would say "let `C` be on of the categories `CompHaus` or `Profinite`, then the following holds: ...". This was not possible in Lean using the old definitions. Using the new definitions, this becomes a matter of identifying what common property -of `CompHaus` and `Profinite` is used in the proof in question, and then proving the theorem for -`CompHausLike P` satisfying that property, and it will automatically apply to both `CompHaus` and +of `CompHaus` and `Profinite` is used in the proof in question, and then proving the theorem for +`CompHausLike P` satisfying that property, and it will automatically apply to both `CompHaus` and `Profinite`. -/ diff --git a/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean b/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean index ae1412b6a3d0d..ec86cd6d90865 100644 --- a/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean +++ b/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean @@ -8,11 +8,11 @@ import Mathlib.Topology.Category.CompHausLike.Limits # The sigma-comparison map -This file defines the map `CompHausLike.sigmaComparison` associated to a presheaf `X` on +This file defines the map `CompHausLike.sigmaComparison` associated to a presheaf `X` on `CompHausLike P`, and a finite family `S₁,...,Sₙ` of spaces in `CompHausLike P`, where `P` is stable under taking finite disjoint unions. -The map `sigmaComparison` is the canonical map `X(S₁ ⊔ ... ⊔ Sₙ) ⟶ X(S₁) × ... × X(Sₙ)` induced by +The map `sigmaComparison` is the canonical map `X(S₁ ⊔ ... ⊔ Sₙ) ⟶ X(S₁) × ... × X(Sₙ)` induced by the inclusion maps `Sᵢ ⟶ S₁ ⊔ ... ⊔ Sₙ`, and it is an isomorphism when `X` preserves finite products. -/ diff --git a/Mathlib/Topology/Category/LightProfinite/Extend.lean b/Mathlib/Topology/Category/LightProfinite/Extend.lean index 55d6645661ad5..bed0658153636 100644 --- a/Mathlib/Topology/Category/LightProfinite/Extend.lean +++ b/Mathlib/Topology/Category/LightProfinite/Extend.lean @@ -10,9 +10,9 @@ import Mathlib.Topology.Category.Profinite.Extend # Extending cones in `LightProfinite` -Let `(Sₙ)_{n : ℕᵒᵖ}` be a sequential inverse system of finite sets and let `S` be -its limit in `Profinite`. Let `G` be a functor from `LightProfinite` to a category `C` and suppose -that `G` preserves the limit described above. Suppose further that the projection maps `S ⟶ Sₙ` are +Let `(Sₙ)_{n : ℕᵒᵖ}` be a sequential inverse system of finite sets and let `S` be +its limit in `Profinite`. Let `G` be a functor from `LightProfinite` to a category `C` and suppose +that `G` preserves the limit described above. Suppose further that the projection maps `S ⟶ Sₙ` are epimorphic for all `n`. Then `G.obj S` is isomorphic to a limit indexed by `StructuredArrow S toLightProfinite` (see `LightProfinite.Extend.isLimitCone`). @@ -21,7 +21,7 @@ We also provide the dual result for a functor of the form `G : LightProfiniteᵒ We apply this to define `LightProfinite.diagram'`, `LightProfinite.asLimitCone'`, and `LightProfinite.asLimit'`, analogues to their unprimed versions in `Mathlib.Topology.Category.LightProfinite.AsLimit`, in which the -indexing category is `StructuredArrow S toLightProfinite` instead of `ℕᵒᵖ`. +indexing category is `StructuredArrow S toLightProfinite` instead of `ℕᵒᵖ`. -/ universe u @@ -37,7 +37,7 @@ variable {F : ℕᵒᵖ ⥤ FintypeCat.{u}} (c : Cone <| F ⋙ toLightProfinite) namespace Extend /-- -Given a sequential cone in `LightProfinite` consisting of finite sets, +Given a sequential cone in `LightProfinite` consisting of finite sets, we obtain a functor from the indexing category to `StructuredArrow c.pt toLightProfinite`. -/ @[simps] @@ -49,7 +49,7 @@ def functor : ℕᵒᵖ ⥤ StructuredArrow c.pt toLightProfinite where example : functor c ⋙ StructuredArrow.proj c.pt toLightProfinite ≅ F := Iso.refl _ /-- -Given a sequential cone in `LightProfinite` consisting of finite sets, +Given a sequential cone in `LightProfinite` consisting of finite sets, we obtain a functor from the opposite of the indexing category to `CostructuredArrow toProfinite.op ⟨c.pt⟩`. -/ @@ -113,7 +113,7 @@ def cone (S : LightProfinite) : example : G.mapCone c = (cone G c.pt).whisker (functor c) := rfl /-- -If `c` and `G.mapCone c` are limit cones and the projection maps in `c` are epimorphic, +If `c` and `G.mapCone c` are limit cones and the projection maps in `c` are epimorphic, then `cone G c.pt` is a limit cone. -/ noncomputable @@ -171,7 +171,7 @@ section LightProfiniteAsLimit variable (S : LightProfinite.{u}) /-- -A functor `StructuredArrow S toLightProfinite ⥤ FintypeCat` whose limit in `LightProfinite` is +A functor `StructuredArrow S toLightProfinite ⥤ FintypeCat` whose limit in `LightProfinite` is isomorphic to `S`. -/ abbrev fintypeDiagram' : StructuredArrow S toLightProfinite ⥤ FintypeCat := diff --git a/Mathlib/Topology/Category/Profinite/Extend.lean b/Mathlib/Topology/Category/Profinite/Extend.lean index 1ac168134b484..8db0cc4dd84e9 100644 --- a/Mathlib/Topology/Category/Profinite/Extend.lean +++ b/Mathlib/Topology/Category/Profinite/Extend.lean @@ -10,9 +10,9 @@ import Mathlib.CategoryTheory.Filtered.Final # Extending cones in `Profinite` -Let `(Sᵢ)_{i : I}` be a family of finite sets indexed by a cofiltered category `I` and let `S` be -its limit in `Profinite`. Let `G` be a functor from `Profinite` to a category `C` and suppose that -`G` preserves the limit described above. Suppose further that the projection maps `S ⟶ Sᵢ` are +Let `(Sᵢ)_{i : I}` be a family of finite sets indexed by a cofiltered category `I` and let `S` be +its limit in `Profinite`. Let `G` be a functor from `Profinite` to a category `C` and suppose that +`G` preserves the limit described above. Suppose further that the projection maps `S ⟶ Sᵢ` are epimorphic for all `i`. Then `G.obj S` is isomorphic to a limit indexed by `StructuredArrow S toProfinite` (see `Profinite.Extend.isLimitCone`). @@ -20,7 +20,7 @@ We also provide the dual result for a functor of the form `G : Profiniteᵒᵖ We apply this to define `Profinite.diagram'`, `Profinite.asLimitCone'`, and `Profinite.asLimit'`, analogues to their unprimed versions in `Mathlib.Topology.Category.Profinite.AsLimit`, in which the -indexing category is `StructuredArrow S toProfinite` instead of `DiscreteQuotient S`. +indexing category is `StructuredArrow S toProfinite` instead of `DiscreteQuotient S`. -/ universe u w @@ -52,7 +52,7 @@ lemma exists_hom (hc : IsLimit c) {X : FintypeCat} (f : c.pt ⟶ toProfinite.obj namespace Extend /-- -Given a cone in `Profinite`, consisting of finite sets and indexed by a cofiltered category, +Given a cone in `Profinite`, consisting of finite sets and indexed by a cofiltered category, we obtain a functor from the indexing category to `StructuredArrow c.pt toProfinite`. -/ @[simps] @@ -64,7 +64,7 @@ def functor : I ⥤ StructuredArrow c.pt toProfinite where example : functor c ⋙ StructuredArrow.proj c.pt toProfinite ≅ F := Iso.refl _ /-- -Given a cone in `Profinite`, consisting of finite sets and indexed by a cofiltered category, +Given a cone in `Profinite`, consisting of finite sets and indexed by a cofiltered category, we obtain a functor from the opposite of the indexing category to `CostructuredArrow toProfinite.op ⟨c.pt⟩`. -/ @@ -136,7 +136,7 @@ def cone (S : Profinite) : example : G.mapCone c = (cone G c.pt).whisker (functor c) := rfl /-- -If `c` and `G.mapCone c` are limit cones and the projection maps in `c` are epimorphic, +If `c` and `G.mapCone c` are limit cones and the projection maps in `c` are epimorphic, then `cone G c.pt` is a limit cone. -/ noncomputable @@ -190,7 +190,7 @@ section ProfiniteAsLimit variable (S : Profinite.{u}) /-- -A functor `StructuredArrow S toProfinite ⥤ FintypeCat` whose limit in `Profinite` is isomorphic +A functor `StructuredArrow S toProfinite ⥤ FintypeCat` whose limit in `Profinite` is isomorphic to `S`. -/ abbrev fintypeDiagram' : StructuredArrow S toProfinite ⥤ FintypeCat := From 7252e9d5bdc8852b57317e27de59855e5a22d299 Mon Sep 17 00:00:00 2001 From: Bryan Gin-ge Chen Date: Tue, 24 Sep 2024 02:37:38 +0000 Subject: [PATCH 110/170] ci: add workflow_dispatch to scheduled workflows (#16862) This will allow anyone with write access to [trigger these workflows manually](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/manually-running-a-workflow) without waiting for the scheduled time. Useful for re-running if something was broken and for testing. I also added / updated comments giving the cron schedules in words (using https://crontab.guru). [Zulip](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Technical.20Debt.20Counters/near/470626800) --- .github/workflows/dependent-issues.yml | 1 + .github/workflows/lean4checker.yml | 1 + .github/workflows/merge_conflicts.yml | 1 + .github/workflows/nightly_bump_toolchain.yml | 2 +- .github/workflows/nightly_merge_master.yml | 3 ++- .github/workflows/nolints.yml | 3 ++- .github/workflows/technical_debt_metrics.yml | 3 ++- .github/workflows/update_dependencies.yml | 1 + 8 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dependent-issues.yml b/.github/workflows/dependent-issues.yml index a73285496116b..9e0b3d2da4b71 100644 --- a/.github/workflows/dependent-issues.yml +++ b/.github/workflows/dependent-issues.yml @@ -3,6 +3,7 @@ name: Dependent Issues on: schedule: - cron: '*/15 * * * *' # run every 15 minutes + workflow_dispatch: jobs: cancel: diff --git a/.github/workflows/lean4checker.yml b/.github/workflows/lean4checker.yml index fdde8c185c5f9..8405cde825320 100644 --- a/.github/workflows/lean4checker.yml +++ b/.github/workflows/lean4checker.yml @@ -4,6 +4,7 @@ name: lean4checker Workflow on: schedule: - cron: '0 0 * * *' # Runs at 00:00 UTC every day + workflow_dispatch: jobs: check-lean4checker: diff --git a/.github/workflows/merge_conflicts.yml b/.github/workflows/merge_conflicts.yml index 68b53db526dad..d10c0233ceaad 100644 --- a/.github/workflows/merge_conflicts.yml +++ b/.github/workflows/merge_conflicts.yml @@ -3,6 +3,7 @@ name: Merge conflicts on: schedule: - cron: '*/15 * * * *' # run every 15 minutes + workflow_dispatch: jobs: main: diff --git a/.github/workflows/nightly_bump_toolchain.yml b/.github/workflows/nightly_bump_toolchain.yml index ed8cd271a71b1..1d53a2c33a3da 100644 --- a/.github/workflows/nightly_bump_toolchain.yml +++ b/.github/workflows/nightly_bump_toolchain.yml @@ -1,9 +1,9 @@ name: Bump lean-toolchain on nightly-testing on: - workflow_dispatch: schedule: - cron: '0 10/3 * * *' # Run every three hours, starting at 11AM CET/2AM PT. + workflow_dispatch: jobs: update-toolchain: diff --git a/.github/workflows/nightly_merge_master.yml b/.github/workflows/nightly_merge_master.yml index 1321c9c54ca3b..d6f2480542294 100644 --- a/.github/workflows/nightly_merge_master.yml +++ b/.github/workflows/nightly_merge_master.yml @@ -4,7 +4,8 @@ name: Merge master to nightly on: schedule: - - cron: '30 */3 * * *' # 8AM CET/11PM PT + - cron: '30 */3 * * *' # At minute 30 past every 3rd hour. + workflow_dispatch: jobs: merge-to-nightly: diff --git a/.github/workflows/nolints.yml b/.github/workflows/nolints.yml index 76f3590e4f585..847e24854e855 100644 --- a/.github/workflows/nolints.yml +++ b/.github/workflows/nolints.yml @@ -2,7 +2,8 @@ name: update nolints on: schedule: - - cron: "0 0 * * 0" + - cron: "0 0 * * 0" # At 00:00 UTC on Sunday. + workflow_dispatch: jobs: build: diff --git a/.github/workflows/technical_debt_metrics.yml b/.github/workflows/technical_debt_metrics.yml index d7055c85e59ae..2a83b1d682cec 100644 --- a/.github/workflows/technical_debt_metrics.yml +++ b/.github/workflows/technical_debt_metrics.yml @@ -2,7 +2,8 @@ name: Weekly Technical Debt Counters on: schedule: - - cron: '0 4 * * 1' # Run at 04:00 every Monday + - cron: '0 4 * * 1' # Run at 04:00 UTC every Monday + workflow_dispatch: jobs: run-script: diff --git a/.github/workflows/update_dependencies.yml b/.github/workflows/update_dependencies.yml index 02779cf664eca..b415c88c6a8c8 100644 --- a/.github/workflows/update_dependencies.yml +++ b/.github/workflows/update_dependencies.yml @@ -3,6 +3,7 @@ name: Update Mathlib Dependencies on: schedule: - cron: '0 * * * *' # This will run every hour + workflow_dispatch: jobs: update-dependencies: From 09caad234f2a2d06b7ba1b8c70fbe3c8cfc4583e Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Tue, 24 Sep 2024 04:03:15 +0000 Subject: [PATCH 111/170] chore: update Mathlib dependencies 2024-09-24 (#17052) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index d035304d7779b..db5f8604eab98 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -25,7 +25,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "61fb4d1a2a6a4fe4be260ca31c58af1234ff298b", + "rev": "a895713f7701e295a015b1087f3113fd3d615272", "name": "aesop", "manifestFile": "lake-manifest.json", "inputRev": "master", From 88dd555b89b39927d5b8f8d10b0b6398d8819a21 Mon Sep 17 00:00:00 2001 From: Dagur Asgeirsson Date: Tue, 24 Sep 2024 05:56:29 +0000 Subject: [PATCH 112/170] feat(Condensed): discrete condensed sets are given by locally constant maps (#15321) This PR proves that under suitable conditions, the functor from the category of sets to the category of sheaves for the coherent topology on `CompHausLike P`, given by mapping a set to the sheaf of locally constant maps to it, is left adjoint to the "underlying set" functor (evaluation at the point). We apply this to prove that the constant sheaf functor into (light) condensed sets is isomorphic to the functor of sheaves of locally constant maps described above. This is the first part of the characterization of discrete condensed objects, see #14027. --- Mathlib.lean | 1 + .../Condensed/Discrete/LocallyConstant.lean | 429 ++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 Mathlib/Condensed/Discrete/LocallyConstant.lean diff --git a/Mathlib.lean b/Mathlib.lean index 064cc2f6fc197..9a201b9b4f9a4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2042,6 +2042,7 @@ import Mathlib.Computability.TuringMachine import Mathlib.Condensed.Basic import Mathlib.Condensed.CartesianClosed import Mathlib.Condensed.Discrete.Basic +import Mathlib.Condensed.Discrete.LocallyConstant import Mathlib.Condensed.Epi import Mathlib.Condensed.Equivalence import Mathlib.Condensed.Explicit diff --git a/Mathlib/Condensed/Discrete/LocallyConstant.lean b/Mathlib/Condensed/Discrete/LocallyConstant.lean new file mode 100644 index 0000000000000..384896122a812 --- /dev/null +++ b/Mathlib/Condensed/Discrete/LocallyConstant.lean @@ -0,0 +1,429 @@ +/- +Copyright (c) 2024 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.Condensed.Discrete.Basic +import Mathlib.Condensed.TopComparison +import Mathlib.Topology.Category.CompHausLike.SigmaComparison +import Mathlib.Topology.FiberPartition +/-! + +# The sheaf of locally constant maps on `CompHausLike P` + +This file proves that under suitable conditions, the functor from the category of sets to the +category of sheaves for the coherent topology on `CompHausLike P`, given by mapping a set to the +sheaf of locally constant maps to it, is left adjoint to the "underlying set" functor (evaluation +at the point). + +We apply this to prove that the constant sheaf functor into (light) condensed sets is isomorphic to +the functor of sheaves of locally constant maps described above. + +## Proof sketch + +The hard part of this adjunction is to define the counit. Its components are defined as follows: + +Let `S : CompHausLike P` and let `Y` be a finite-product preserving presheaf on `CompHausLike P`  +(e.g. a sheaf for the coherent topology). We need to define a map `LocallyConstant S Y(*) ⟶ Y(S)`. +Given a locally constant map `f : S → Y(*)`, let `S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding +decomposition of `S` into the fibers. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ` and denote +by `gᵢ` the canonical map `Y(*) → Y(Sᵢ)`. Our map then takes `f` to the image of +`(g₁(y₁), ⋯, gₙ(yₙ))` under the isomorphism `Y(S₁) × ⋯ × Y(Sₙ) ≅ Y(S₁ ⊔ ⋯ ⊔ Sₙ) = Y(S)`. + +Now we need to prove that the counit is natural in `S : CompHausLike P` and +`Y : Sheaf (coherentTopology (CompHausLike P)) (Type _)`. There are two key lemmas in all +naturality proofs in this file (both lemmas are in the `CompHausLike.LocallyConstant` namespace): + +* `presheaf_ext`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, another presheaf + `X`, and two elements `x y : X(S)`, to prove that `x = y` it suffices to prove that for every + inclusion map `ιᵢ : Sᵢ ⟶ S`, `X(ιᵢ)(x) = X(ιᵢ)(y)`. + Here it is important that we set everything up in such a way that the `Sᵢ` are literally subtypes + of `S`.  + +* `incl_of_counitAppApp`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, we have + `Y(ιᵢ)(ε_{S, Y}(f)) = gᵢ(yᵢ)` where `ε` denotes the counit and the other notation is like above. + +## Main definitions + +* `CompHausLike.LocallyConstant.functor`: the functor from the category of sets to the category of + sheaves for the coherent topology on `CompHausLike P`, which takes a set `X` to + `LocallyConstant - X` + - `CondensedSet.LocallyConstant.functor` is the above functor in the case of condensed sets. + - `LightCondSet.LocallyConstant.functor` is the above functor in the case of light condensed sets. + +* `CompHausLike.LocallyConstant.adjunction`: the functor described above is left adjoint to the + "underlying set" functor `(sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩`, which takes + a sheaf `X` to the set `X(*)`. + +* `CondensedSet.LocallyConstant.iso`: the functor `CondensedSet.LocallyConstant.functor` is + isomorphic to the functor `Condensed.discrete (Type _)` (the constant sheaf functor from sets to + condensed sets). + +* `LightCondSet.LocallyConstant.iso`: the functor `LightCondSet.LocallyConstant.functor` is + isomorphic to the functor `LightCondensed.discrete (Type _)` (the constant sheaf functor from sets + to light condensed sets). + +-/ + +universe u w + +open CategoryTheory Limits LocallyConstant TopologicalSpace.Fiber Opposite Function Fiber + +attribute [local instance] ConcreteCategory.instFunLike + +variable {P : TopCat.{u} → Prop} + +namespace CompHausLike.LocallyConstant + +/-- +The functor from the category of sets to presheaves on `CompHausLike P` given by locally constant +maps. +-/ +@[simps] +def functorToPresheaves : Type (max u w) ⥤ ((CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w) where + obj X := { + obj := fun ⟨S⟩ ↦ LocallyConstant S X + map := fun f g ↦ g.comap f.unop } + map f := { app := fun S t ↦ t.map f } + +/-- +Locally constant maps are the same as continuous maps when the target is equipped with the discrete +topology +-/ +@[simps] +def locallyConstantIsoContinuousMap (Y X : Type*) [TopologicalSpace Y] : + LocallyConstant Y X ≅ C(Y, TopCat.discrete.obj X) := + letI : TopologicalSpace X := ⊥ + haveI : DiscreteTopology X := ⟨rfl⟩ + { hom := fun f ↦ (f : C(Y, X)) + inv := fun f ↦ ⟨f, (IsLocallyConstant.iff_continuous f).mpr f.2⟩ } + +section Adjunction + +variable [∀ (S : CompHausLike.{u} P) (p : S → Prop), HasProp P (Subtype p)] + +section + +variable {Q : CompHausLike.{u} P} {Z : Type max u w} (r : LocallyConstant Q Z) (a : Fiber r) + +/-- A fiber of a locally constant map as a `CompHausLike P`. -/ +def fiber : CompHausLike.{u} P := CompHausLike.of P a.val + +instance : HasProp P (fiber r a) := inferInstanceAs (HasProp P (Subtype _)) + +/-- The inclusion map from a component of the coproduct induced by `f` into `S`. -/ +def sigmaIncl : fiber r a ⟶ Q := TopologicalSpace.Fiber.sigmaIncl _ a + +/-- The canonical map from the coproduct induced by `f` to `S` as an isomorphism in +`CompHausLike P`. -/ +noncomputable def sigmaIso [HasExplicitFiniteCoproducts.{u} P] : (finiteCoproduct (fiber r)) ≅ Q := + isoOfBijective (sigmaIsoHom r) ⟨sigmaIsoHom_inj r, sigmaIsoHom_surj r⟩ + +lemma sigmaComparison_comp_sigmaIso [HasExplicitFiniteCoproducts.{u} P] + (X : (CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w) : + (X.mapIso (sigmaIso r).op).hom ≫ sigmaComparison X (fun a ↦ (fiber r a).1) ≫ + (fun g ↦ g a) = X.map (sigmaIncl r a).op := by + ext + simp only [Functor.mapIso_hom, Iso.op_hom, types_comp_apply, sigmaComparison, coe_of, + ← FunctorToTypes.map_comp_apply] + rfl + +end + +variable {S : CompHausLike.{u} P} {Y : (CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w} + [HasProp P PUnit.{u+1}] (f : LocallyConstant S (Y.obj (op (CompHausLike.of P PUnit.{u+1})))) + +/-- The projection of the counit. -/ +noncomputable def counitAppAppImage : (a : Fiber f) → Y.obj ⟨fiber f a⟩ := + fun a ↦ Y.map (CompHausLike.isTerminalPUnit.from _).op a.image + +/-- +The counit is defined as follows: given a locally constant map `f : S → Y(*)`, let +`S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding decomposition of `S` into the fibers. We need to provide an +element of `Y(S)`. It suffices to provide an element of `Y(Sᵢ)` for all `i`. Let `yᵢ ∈ Y(*)` denote +the value of `f` on `Sᵢ`. Our desired element is the image of `yᵢ` under the canonical map +`Y(*) → Y(Sᵢ)`. +-/ +noncomputable def counitAppApp (S : CompHausLike.{u} P) (Y : (CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w) + [PreservesFiniteProducts Y] [HasExplicitFiniteCoproducts.{u} P] : + LocallyConstant S (Y.obj (op (CompHausLike.of P PUnit.{u+1}))) ⟶ Y.obj ⟨S⟩ := + fun r ↦ ((inv (sigmaComparison Y (fun a ↦ (fiber r a).1))) ≫ + (Y.mapIso (sigmaIso r).op).inv) (counitAppAppImage r) + +-- This is the key lemma to prove naturality of the counit: +/-- +To check equality of two elements of `X(S)`, it suffices to check equality after composing with +each `X(S) → X(Sᵢ)`. +-/ +lemma presheaf_ext (X : (CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w) + [PreservesFiniteProducts X] (x y : X.obj ⟨S⟩) + [HasExplicitFiniteCoproducts.{u} P] + (h : ∀ (a : Fiber f), X.map (sigmaIncl f a).op x = X.map (sigmaIncl f a).op y) : x = y := by + apply injective_of_mono (X.mapIso (sigmaIso f).op).hom + apply injective_of_mono (sigmaComparison X (fun a ↦ (fiber f a).1)) + ext a + specialize h a + rw [← sigmaComparison_comp_sigmaIso] at h + exact h + +lemma incl_of_counitAppApp [PreservesFiniteProducts Y] [HasExplicitFiniteCoproducts.{u} P] + (a : Fiber f) : Y.map (sigmaIncl f a).op (counitAppApp S Y f) = counitAppAppImage f a := by + rw [← sigmaComparison_comp_sigmaIso, Functor.mapIso_hom, Iso.op_hom, types_comp_apply] + simp only [counitAppApp, Functor.mapIso_inv, ← Iso.op_hom, types_comp_apply, + ← FunctorToTypes.map_comp_apply, Iso.inv_hom_id, FunctorToTypes.map_id_apply] + exact congrFun (inv_hom_id_apply (asIso (sigmaComparison Y (fun a ↦ (fiber f a).1))) + (counitAppAppImage f)) _ + +variable {T : CompHausLike.{u} P} (g : T ⟶ S) + +/-- +This is an auxiliary definition, the details do not matter. What's important is that this map exists +so that the lemma `incl_comap` works. +-/ +def componentHom (a : Fiber (f.comap g)) : + fiber _ a ⟶ fiber _ (Fiber.mk f (g a.preimage)) where + toFun x := ⟨g x.val, by + simp only [Fiber.mk, Set.mem_preimage, Set.mem_singleton_iff] + convert map_eq_image _ _ x + exact map_preimage_eq_image_map _ _ a⟩ + continuous_toFun := by + exact Continuous.subtype_mk (Continuous.comp g.continuous continuous_subtype_val) _ + -- term mode gives "unknown free variable" error. + +lemma incl_comap {S T : (CompHausLike P)ᵒᵖ} + (f : LocallyConstant S.unop (Y.obj (op (CompHausLike.of P PUnit.{u+1})))) + (g : S ⟶ T) (a : Fiber (f.comap g.unop)) : + g ≫ (sigmaIncl (f.comap g.unop) a).op = + (sigmaIncl f _).op ≫ (componentHom f g.unop a).op := + rfl + +/-- The counit is natural in `S : CompHausLike P` -/ +@[simps!] +noncomputable def counitApp [HasExplicitFiniteCoproducts.{u} P] + (Y : (CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w) [PreservesFiniteProducts Y] : + (functorToPresheaves.obj (Y.obj (op (CompHausLike.of P PUnit.{u+1})))) ⟶ Y where + app := fun ⟨S⟩ ↦ counitAppApp S Y + naturality := by + intro S T g + ext f + apply presheaf_ext (f.comap g.unop) + intro a + simp only [op_unop, functorToPresheaves_obj_obj, types_comp_apply, functorToPresheaves_obj_map, + incl_of_counitAppApp, ← FunctorToTypes.map_comp_apply, incl_comap] + simp only [FunctorToTypes.map_comp_apply, incl_of_counitAppApp] + simp only [counitAppAppImage, ← FunctorToTypes.map_comp_apply, ← op_comp, + terminal.comp_from] + apply congrArg + exact image_eq_image_mk (g := g.unop) (a := a) + +variable (P) (X : TopCat.{max u w}) + [HasExplicitFiniteCoproducts.{0} P] [HasExplicitPullbacks P] + (hs : ∀ ⦃X Y : CompHausLike P⦄ (f : X ⟶ Y), EffectiveEpi f → Function.Surjective f) + +/-- `locallyConstantIsoContinuousMap` is a natural isomorphism. -/ +noncomputable def functorToPresheavesIsoTopCatToSheafCompHausLike (X : Type (max u w)) : + functorToPresheaves.{u, w}.obj X ≅ + ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).val := + NatIso.ofComponents (fun S ↦ locallyConstantIsoContinuousMap _ _) + +/-- `CompHausLike.LocallyConstant.functorToPresheaves` lands in sheaves. -/ +@[simps] +def functor : + have := CompHausLike.preregular hs + Type (max u w) ⥤ Sheaf (coherentTopology (CompHausLike.{u} P)) (Type (max u w)) where + obj X := { + val := functorToPresheaves.{u, w}.obj X + cond := by + rw [Presheaf.isSheaf_of_iso_iff (functorToPresheavesIsoTopCatToSheafCompHausLike P hs X)] + exact ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).cond } + map f := ⟨functorToPresheaves.{u, w}.map f⟩ + +/-- +`CompHausLike.LocallyConstant.functor` is naturally isomorphic to the restriction of +`topCatToSheafCompHausLike` to discrete topological spaces. +-/ +noncomputable def functorIsoTopCatToSheafCompHausLike : + functor.{u, w} P hs ≅ TopCat.discrete.{max w u} ⋙ topCatToSheafCompHausLike P hs := + NatIso.ofComponents (fun X ↦ (fullyFaithfulSheafToPresheaf _ _).preimageIso + (functorToPresheavesIsoTopCatToSheafCompHausLike P hs X)) + +/-- The counit is natural in both `S : CompHausLike P` and +`Y : Sheaf (coherentTopology (CompHausLike P)) (Type (max u w))` -/ +@[simps] +noncomputable def counit [HasExplicitFiniteCoproducts.{u} P] : haveI := CompHausLike.preregular hs + (sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩ ⋙ functor.{u, w} P hs ⟶ + 𝟭 (Sheaf (coherentTopology (CompHausLike.{u} P)) (Type (max u w))) where + app X := haveI := CompHausLike.preregular hs + ⟨counitApp X.val⟩ + naturality X Y g := by + have := CompHausLike.preregular hs + apply Sheaf.hom_ext + simp only [functor, id_eq, eq_mpr_eq_cast, Functor.comp_obj, Functor.flip_obj_obj, + sheafToPresheaf_obj, Functor.id_obj, Functor.comp_map, Functor.flip_obj_map, + sheafToPresheaf_map, Sheaf.instCategorySheaf_comp_val, Functor.id_map] + ext S (f : LocallyConstant _ _) + simp only [FunctorToTypes.comp, counitApp_app] + apply presheaf_ext (f.map (g.val.app (op (CompHausLike.of P PUnit.{u+1})))) + intro a + simp only [op_unop, functorToPresheaves_map_app, incl_of_counitAppApp] + apply presheaf_ext (f.comap (sigmaIncl _ _)) + intro b + simp only [counitAppAppImage, ← FunctorToTypes.map_comp_apply, ← op_comp, CompHausLike.coe_of, + map_apply, IsTerminal.comp_from, ← map_preimage_eq_image_map] + change (_ ≫ Y.val.map _) _ = (_ ≫ Y.val.map _) _ + simp only [← g.val.naturality, + show sigmaIncl (f.comap (sigmaIncl (f.map _) a)) b ≫ sigmaIncl (f.map _) a = + (sigmaInclIncl f _ a b) ≫ sigmaIncl f (Fiber.mk f _) from rfl] + simp only [op_comp, Functor.map_comp, types_comp_apply, incl_of_counitAppApp] + simp only [counitAppAppImage, ← FunctorToTypes.map_comp_apply, ← op_comp, terminal.comp_from] + rw [mk_image] + change (X.val.map _ ≫ _) _ = (X.val.map _ ≫ _) _ + simp only [g.val.naturality] + simp only [types_comp_apply] + have := map_preimage_eq_image (f := g.val.app _ ∘ f) (a := a) + simp only [Function.comp_apply] at this + rw [this] + apply congrArg + symm + convert (b.preimage).prop + exact (mem_iff_eq_image (g.val.app _ ∘ f) _ _).symm + +/-- +The unit of the adjunciton is given by mapping each element to the corresponding constant map. +-/ +@[simps] +def unit : 𝟭 _ ⟶ functor P hs ⋙ (sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩ where + app X x := LocallyConstant.const _ x + +/-- The unit of the adjunction is an iso. -/ +noncomputable def unitIso : 𝟭 (Type max u w) ≅ functor.{u, w} P hs ⋙ + (sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩ where + hom := unit P hs + inv := { app := fun X f ↦ f.toFun PUnit.unit } + +lemma adjunction_left_triangle [HasExplicitFiniteCoproducts.{u} P] + (X : Type max u w) : functorToPresheaves.{u, w}.map ((unit P hs).app X) ≫ + ((counit P hs).app ((functor P hs).obj X)).val = 𝟙 (functorToPresheaves.obj X) := by + ext ⟨S⟩ (f : LocallyConstant _ X) + simp only [Functor.id_obj, Functor.comp_obj, FunctorToTypes.comp, NatTrans.id_app, + functorToPresheaves_obj_obj, types_id_apply] + simp only [counit, counitApp_app] + have := CompHausLike.preregular hs + apply presheaf_ext + (X := ((functor P hs).obj X).val) (Y := ((functor.{u, w} P hs).obj X).val) + (f.map ((unit P hs).app X)) + intro a + erw [incl_of_counitAppApp] + simp only [functor_obj_val, functorToPresheaves_obj_obj, coe_of, Functor.id_obj, + counitAppAppImage, LocallyConstant.map_apply, functorToPresheaves_obj_map, Quiver.Hom.unop_op] + ext x + erw [← map_eq_image _ a x] + rfl + +/-- +`CompHausLike.LocallyConstant.functor` is left adjoint to the forgetful functor. +-/ +@[simps] +noncomputable def adjunction [HasExplicitFiniteCoproducts.{u} P] : + functor.{u, w} P hs ⊣ (sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩ where + unit := unit P hs + counit := counit P hs + left_triangle_components := by + intro X + simp only [Functor.comp_obj, Functor.id_obj, NatTrans.comp_app, Functor.flip_obj_obj, + sheafToPresheaf_obj, functor_obj_val, functorToPresheaves_obj_obj, coe_of, whiskerRight_app, + Functor.associator_hom_app, whiskerLeft_app, Category.id_comp, NatTrans.id_app'] + apply Sheaf.hom_ext + rw [Sheaf.instCategorySheaf_comp_val, Sheaf.instCategorySheaf_id_val] + exact adjunction_left_triangle P hs X + right_triangle_components := by + intro X + ext (x : X.val.obj _) + simp only [Functor.comp_obj, Functor.id_obj, Functor.flip_obj_obj, sheafToPresheaf_obj, + FunctorToTypes.comp, whiskerLeft_app, unit_app, coe_of, Functor.associator_inv_app, + functor_obj_val, functorToPresheaves_obj_obj, types_id_apply, whiskerRight_app, + Functor.flip_obj_map, sheafToPresheaf_map, counit_app_val, counitApp_app, NatTrans.id_app'] + have := CompHausLike.preregular hs + letI : PreservesFiniteProducts ((sheafToPresheaf (coherentTopology _) _).obj X) := + inferInstanceAs (PreservesFiniteProducts (Sheaf.val _)) + apply presheaf_ext ((unit P hs).app _ x) + intro a + erw [incl_of_counitAppApp] + simp only [sheafToPresheaf_obj, unit_app, coe_of, counitAppAppImage, coe_const] + erw [← map_eq_image _ a ⟨PUnit.unit, by simp [mem_iff_eq_image, ← map_preimage_eq_image]⟩] + rfl + +instance [HasExplicitFiniteCoproducts.{u} P] : IsIso (adjunction P hs).unit := + inferInstanceAs (IsIso (unitIso P hs).hom) + +end Adjunction + +end CompHausLike.LocallyConstant + +section Condensed + +open Condensed CompHausLike + +namespace CondensedSet.LocallyConstant + +/-- The functor from sets to condensed sets given by locally constant maps into the set. -/ +abbrev functor : Type (u+1) ⥤ CondensedSet.{u} := + CompHausLike.LocallyConstant.functor.{u, u+1} (P := fun _ ↦ True) + (hs := fun _ _ _ ↦ ((CompHaus.effectiveEpi_tfae _).out 0 2).mp) + +/-- +`CondensedSet.LocallyConstant.functor` is isomorphic to `Condensed.discrete` +(by uniqueness of adjoints). +-/ +noncomputable def iso : functor ≅ discrete (Type (u+1)) := + (LocallyConstant.adjunction _ _).leftAdjointUniq (discreteUnderlyingAdj _) + +/-- `CondensedSet.LocallyConstant.functor` is fully faithful. -/ +noncomputable def functorFullyFaithful : functor.FullyFaithful := + (LocallyConstant.adjunction.{u, u+1} _ _).fullyFaithfulLOfIsIsoUnit + +noncomputable instance : functor.Faithful := functorFullyFaithful.faithful + +noncomputable instance : functor.Full := functorFullyFaithful.full + +instance : (discrete (Type _)).Faithful := Functor.Faithful.of_iso iso + +noncomputable instance : (discrete (Type _)).Full := Functor.Full.of_iso iso + +end CondensedSet.LocallyConstant + +namespace LightCondSet.LocallyConstant + +/-- The functor from sets to light condensed sets given by locally constant maps into the set. -/ +abbrev functor : Type u ⥤ LightCondSet.{u} := + CompHausLike.LocallyConstant.functor.{u, u} + (P := fun X ↦ TotallyDisconnectedSpace X ∧ SecondCountableTopology X) + (hs := fun _ _ _ ↦ (LightProfinite.effectiveEpi_iff_surjective _).mp) + +instance (S : LightProfinite.{u}) (p : S → Prop) : + HasProp (fun X ↦ TotallyDisconnectedSpace X ∧ SecondCountableTopology X) (Subtype p) := + ⟨⟨(inferInstance : TotallyDisconnectedSpace (Subtype p)), + (inferInstance : SecondCountableTopology {s | p s})⟩⟩ + +/-- +`LightCondSet.LocallyConstant.functor` is isomorphic to `LightCondensed.discrete` +(by uniqueness of adjoints). +-/ +noncomputable def iso : functor ≅ LightCondensed.discrete (Type u) := + (LocallyConstant.adjunction _ _).leftAdjointUniq (LightCondensed.discreteUnderlyingAdj _) + +/-- `LightCondSet.LocallyConstant.functor` is fully faithful. -/ +noncomputable def functorFullyFaithful : functor.{u}.FullyFaithful := + (LocallyConstant.adjunction _ _).fullyFaithfulLOfIsIsoUnit + +instance : functor.{u}.Faithful := functorFullyFaithful.faithful + +instance : LightCondSet.LocallyConstant.functor.Full := functorFullyFaithful.full + +instance : (LightCondensed.discrete (Type u)).Faithful := Functor.Faithful.of_iso iso.{u} + +instance : (LightCondensed.discrete (Type u)).Full := Functor.Full.of_iso iso.{u} + +end LightCondSet.LocallyConstant + +end Condensed From 4b28fd7c07daa4ca1a4af2c1807bd586b0111d3d Mon Sep 17 00:00:00 2001 From: sgouezel Date: Tue, 24 Sep 2024 06:06:02 +0000 Subject: [PATCH 113/170] feat: define `HasSummableGeomSeries` to unify results between normed field and complete normed algebras (#17002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, several analogous results are proved separately in complete normed algebras, and in normed fields. For instance, the fact that inversion is differentiable is called `differentiableAt_inv'` in the former, and `differentiableAt_inv` in the latter, with similar proofs relying on the convergence of geometric series, due to completeness in the former and to the existence of the inverse in the latter. We unify these results by defining a typeclass `HasSummableGeomSeries` saying that `∑ x ^ n` converges for all `x` with norm `< 1`. We show that this is satisfied both in complete normed rings and in normed fields. And we show that many results follow solely from this assumption, deduplicating statements and proofs. Along the way, we show that inversion is analytic on rings with summable geometric series, and deduce in particular that it is strictly differentiable, clearing an existing TODO. This adds a few imports (importing analytic functions in files where they were not needed before), but with the upcoming refactor of smooth functions, analytic functions will in any case need to be imported earlier on, so this doesn't look like a real issue to me. --- Mathlib/Analysis/Analytic/Constructions.lean | 102 ++++-- Mathlib/Analysis/Calculus/Deriv/Inv.lean | 35 +-- Mathlib/Analysis/Calculus/DiffContOnCl.lean | 3 +- Mathlib/Analysis/Calculus/Dslope.lean | 4 +- .../Analysis/Calculus/FDeriv/Analytic.lean | 6 + Mathlib/Analysis/Calculus/FDeriv/Mul.lean | 75 +++-- Mathlib/Analysis/Normed/Algebra/Spectrum.lean | 4 +- Mathlib/Analysis/Normed/Ring/Units.lean | 59 ++-- .../NormedSpace/Multilinear/Basic.lean | 6 + Mathlib/Analysis/SpecificLimits/Normed.lean | 291 +++++++++++------- .../NumberTheory/LSeries/AbstractFuncEq.lean | 2 +- Mathlib/Tactic/FunProp/Differentiable.lean | 3 - 12 files changed, 357 insertions(+), 233 deletions(-) diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index fb1f04b56cf27..5b268c5b5d826 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -6,6 +6,7 @@ Authors: David Loeffler, Geoffrey Irving import Mathlib.Analysis.Analytic.Composition import Mathlib.Analysis.Analytic.Linear import Mathlib.Analysis.NormedSpace.OperatorNorm.Mul +import Mathlib.Analysis.Normed.Ring.Units /-! # Various ways to combine analytic functions @@ -603,19 +604,36 @@ lemma AnalyticOn.pow {f : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (n : section Geometric variable (𝕜 A : Type*) [NontriviallyNormedField 𝕜] [NormedRing A] [NormedAlgebra 𝕜 A] - [NormOneClass A] /-- The geometric series `1 + x + x ^ 2 + ...` as a `FormalMultilinearSeries`. -/ def formalMultilinearSeries_geometric : FormalMultilinearSeries 𝕜 A A := fun n ↦ ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 n A -lemma formalMultilinearSeries_geometric_apply_norm (n : ℕ) : +lemma formalMultilinearSeries_geometric_apply_norm_le (n : ℕ) : + ‖formalMultilinearSeries_geometric 𝕜 A n‖ ≤ max 1 ‖(1 : A)‖ := + ContinuousMultilinearMap.norm_mkPiAlgebraFin_le + +lemma formalMultilinearSeries_geometric_apply_norm [NormOneClass A] (n : ℕ) : ‖formalMultilinearSeries_geometric 𝕜 A n‖ = 1 := ContinuousMultilinearMap.norm_mkPiAlgebraFin end Geometric -lemma formalMultilinearSeries_geometric_radius (𝕜) [NontriviallyNormedField 𝕜] +lemma one_le_formalMultilinearSeries_geometric_radius (𝕜 : Type*) [NontriviallyNormedField 𝕜] + (A : Type*) [NormedRing A] [NormedAlgebra 𝕜 A] : + 1 ≤ (formalMultilinearSeries_geometric 𝕜 A).radius := by + refine le_of_forall_nnreal_lt (fun r hr ↦ ?_) + rw [← Nat.cast_one, ENNReal.coe_lt_natCast, Nat.cast_one] at hr + apply FormalMultilinearSeries.le_radius_of_isBigO + apply isBigO_of_le' (c := max 1 ‖(1 : A)‖) atTop (fun n ↦ ?_) + simp only [norm_mul, norm_norm, norm_pow, Real.norm_eq_abs, NNReal.abs_eq, norm_one, mul_one, + abs_norm] + apply le_trans ?_ (formalMultilinearSeries_geometric_apply_norm_le 𝕜 A n) + conv_rhs => rw [← mul_one (‖formalMultilinearSeries_geometric 𝕜 A n‖)] + gcongr + exact pow_le_one _ (coe_nonneg r) hr.le + +lemma formalMultilinearSeries_geometric_radius (𝕜 : Type*) [NontriviallyNormedField 𝕜] (A : Type*) [NormedRing A] [NormOneClass A] [NormedAlgebra 𝕜 A] : (formalMultilinearSeries_geometric 𝕜 A).radius = 1 := by apply le_antisymm @@ -641,20 +659,61 @@ lemma formalMultilinearSeries_geometric_radius (𝕜) [NontriviallyNormedField rw [norm_one, Real.norm_of_nonneg (pow_nonneg (coe_nonneg r) _)] exact pow_le_one _ (coe_nonneg r) hr.le -lemma hasFPowerSeriesOnBall_inv_one_sub - (𝕜 𝕝 : Type*) [NontriviallyNormedField 𝕜] [NontriviallyNormedField 𝕝] [NormedAlgebra 𝕜 𝕝] : - HasFPowerSeriesOnBall (fun x : 𝕝 ↦ (1 - x)⁻¹) (formalMultilinearSeries_geometric 𝕜 𝕝) 0 1 := by +lemma hasFPowerSeriesOnBall_inverse_one_sub + (𝕜 : Type*) [NontriviallyNormedField 𝕜] + (A : Type*) [NormedRing A] [NormedAlgebra 𝕜 A] [HasSummableGeomSeries A] : + HasFPowerSeriesOnBall (fun x : A ↦ Ring.inverse (1 - x)) + (formalMultilinearSeries_geometric 𝕜 A) 0 1 := by constructor - · exact le_of_eq (formalMultilinearSeries_geometric_radius 𝕜 𝕝).symm + · exact one_le_formalMultilinearSeries_geometric_radius 𝕜 A · exact one_pos · intro y hy - simp_rw [zero_add, formalMultilinearSeries_geometric, - ContinuousMultilinearMap.mkPiAlgebraFin_apply, - List.prod_ofFn, Finset.prod_const, - Finset.card_univ, Fintype.card_fin] - apply hasSum_geometric_of_norm_lt_one - simpa only [← ofReal_one, Metric.emetric_ball, Metric.ball, - dist_eq_norm, sub_zero] using hy + simp only [EMetric.mem_ball, edist_dist, dist_zero_right, ofReal_lt_one] at hy + simp only [zero_add, NormedRing.inverse_one_sub _ hy, Units.oneSub, Units.inv_mk, + formalMultilinearSeries_geometric, ContinuousMultilinearMap.mkPiAlgebraFin_apply, + List.ofFn_const, List.prod_replicate] + exact (summable_geometric_of_norm_lt_one hy).hasSum + +lemma analyticAt_inverse_one_sub (𝕜 : Type*) [NontriviallyNormedField 𝕜] + (A : Type*) [NormedRing A] [NormedAlgebra 𝕜 A] [HasSummableGeomSeries A] : + AnalyticAt 𝕜 (fun x : A ↦ Ring.inverse (1 - x)) 0 := + ⟨_, ⟨_, hasFPowerSeriesOnBall_inverse_one_sub 𝕜 A⟩⟩ + +/-- If `A` is a normed algebra over `𝕜` with summable geometric series, then inversion on `A` is +analytic at any unit. -/ +lemma analyticAt_inverse {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] [HasSummableGeomSeries A] (z : Aˣ) : + AnalyticAt 𝕜 Ring.inverse (z : A) := by + rcases subsingleton_or_nontrivial A with hA|hA + · convert analyticAt_const (v := (0 : A)) + · let f1 : A → A := fun a ↦ a * z.inv + let f2 : A → A := fun b ↦ Ring.inverse (1 - b) + let f3 : A → A := fun c ↦ 1 - z.inv * c + have feq : ∀ᶠ y in 𝓝 (z : A), (f1 ∘ f2 ∘ f3) y = Ring.inverse y := by + have : Metric.ball (z : A) (‖(↑z⁻¹ : A)‖⁻¹) ∈ 𝓝 (z : A) := by + apply Metric.ball_mem_nhds + simp + filter_upwards [this] with y hy + simp only [Metric.mem_ball, dist_eq_norm] at hy + have : y = Units.ofNearby z y hy := rfl + rw [this, Eq.comm] + simp only [Ring.inverse_unit, Function.comp_apply] + simp [Units.ofNearby, f1, f2, f3, Units.add, _root_.mul_sub] + rw [← Ring.inverse_unit] + congr + simp + apply AnalyticAt.congr _ feq + apply (analyticAt_id.mul analyticAt_const).comp + apply AnalyticAt.comp + · simp only [Units.inv_eq_val_inv, Units.inv_mul, sub_self, f2, f3] + exact analyticAt_inverse_one_sub 𝕜 A + · exact analyticAt_const.sub (analyticAt_const.mul analyticAt_id) + +lemma hasFPowerSeriesOnBall_inv_one_sub + (𝕜 𝕝 : Type*) [NontriviallyNormedField 𝕜] [NontriviallyNormedField 𝕝] [NormedAlgebra 𝕜 𝕝] : + HasFPowerSeriesOnBall (fun x : 𝕝 ↦ (1 - x)⁻¹) (formalMultilinearSeries_geometric 𝕜 𝕝) 0 1 := by + convert hasFPowerSeriesOnBall_inverse_one_sub 𝕜 𝕝 + exact Ring.inverse_eq_inv'.symm lemma analyticAt_inv_one_sub (𝕝 : Type*) [NontriviallyNormedField 𝕝] [NormedAlgebra 𝕜 𝕝] : AnalyticAt 𝕜 (fun x : 𝕝 ↦ (1 - x)⁻¹) 0 := @@ -663,19 +722,8 @@ lemma analyticAt_inv_one_sub (𝕝 : Type*) [NontriviallyNormedField 𝕝] [Norm /-- If `𝕝` is a normed field extension of `𝕜`, then the inverse map `𝕝 → 𝕝` is `𝕜`-analytic away from 0. -/ lemma analyticAt_inv {z : 𝕝} (hz : z ≠ 0) : AnalyticAt 𝕜 Inv.inv z := by - let f1 : 𝕝 → 𝕝 := fun a ↦ 1 / z * a - let f2 : 𝕝 → 𝕝 := fun b ↦ (1 - b)⁻¹ - let f3 : 𝕝 → 𝕝 := fun c ↦ 1 - c / z - have feq : f1 ∘ f2 ∘ f3 = Inv.inv := by - ext1 x - dsimp only [f1, f2, f3, Function.comp_apply] - field_simp - have f3val : f3 z = 0 := by simp only [f3, div_self hz, sub_self] - have f3an : AnalyticAt 𝕜 f3 z := by - apply analyticAt_const.sub - simpa only [div_eq_inv_mul] using analyticAt_const.mul analyticAt_id - exact feq ▸ (analyticAt_const.mul analyticAt_id).comp - ((f3val.symm ▸ analyticAt_inv_one_sub 𝕝).comp f3an) + convert analyticAt_inverse (𝕜 := 𝕜) (Units.mk0 _ hz) + exact Ring.inverse_eq_inv'.symm /-- `x⁻¹` is analytic away from zero -/ lemma analyticOn_inv : AnalyticOn 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := by diff --git a/Mathlib/Analysis/Calculus/Deriv/Inv.lean b/Mathlib/Analysis/Calculus/Deriv/Inv.lean index ffa6762826f8e..8687b3af9373d 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Inv.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Inv.lean @@ -63,20 +63,13 @@ theorem hasDerivWithinAt_inv (x_ne_zero : x ≠ 0) (s : Set 𝕜) : HasDerivWithinAt (fun x => x⁻¹) (-(x ^ 2)⁻¹) s x := (hasDerivAt_inv x_ne_zero).hasDerivWithinAt -theorem differentiableAt_inv : DifferentiableAt 𝕜 (fun x => x⁻¹) x ↔ x ≠ 0 := +theorem differentiableAt_inv_iff : DifferentiableAt 𝕜 (fun x => x⁻¹) x ↔ x ≠ 0 := ⟨fun H => NormedField.continuousAt_inv.1 H.continuousAt, fun H => (hasDerivAt_inv H).differentiableAt⟩ -theorem differentiableWithinAt_inv (x_ne_zero : x ≠ 0) : - DifferentiableWithinAt 𝕜 (fun x => x⁻¹) s x := - (differentiableAt_inv.2 x_ne_zero).differentiableWithinAt - -theorem differentiableOn_inv : DifferentiableOn 𝕜 (fun x : 𝕜 => x⁻¹) { x | x ≠ 0 } := fun _x hx => - differentiableWithinAt_inv hx - theorem deriv_inv : deriv (fun x => x⁻¹) x = -(x ^ 2)⁻¹ := by rcases eq_or_ne x 0 with (rfl | hne) - · simp [deriv_zero_of_not_differentiableAt (mt differentiableAt_inv.1 (not_not.2 rfl))] + · simp [deriv_zero_of_not_differentiableAt (mt differentiableAt_inv_iff.1 (not_not.2 rfl))] · exact (hasDerivAt_inv hne).deriv @[simp] @@ -85,13 +78,17 @@ theorem deriv_inv' : (deriv fun x : 𝕜 => x⁻¹) = fun x => -(x ^ 2)⁻¹ := theorem derivWithin_inv (x_ne_zero : x ≠ 0) (hxs : UniqueDiffWithinAt 𝕜 s x) : derivWithin (fun x => x⁻¹) s x = -(x ^ 2)⁻¹ := by - rw [DifferentiableAt.derivWithin (differentiableAt_inv.2 x_ne_zero) hxs] + rw [DifferentiableAt.derivWithin (differentiableAt_inv x_ne_zero) hxs] exact deriv_inv theorem hasFDerivAt_inv (x_ne_zero : x ≠ 0) : HasFDerivAt (fun x => x⁻¹) (smulRight (1 : 𝕜 →L[𝕜] 𝕜) (-(x ^ 2)⁻¹) : 𝕜 →L[𝕜] 𝕜) x := hasDerivAt_inv x_ne_zero +theorem hasStrictFDerivAt_inv (x_ne_zero : x ≠ 0) : + HasStrictFDerivAt (fun x => x⁻¹) (smulRight (1 : 𝕜 →L[𝕜] 𝕜) (-(x ^ 2)⁻¹) : 𝕜 →L[𝕜] 𝕜) x := + hasStrictDerivAt_inv x_ne_zero + theorem hasFDerivWithinAt_inv (x_ne_zero : x ≠ 0) : HasFDerivWithinAt (fun x => x⁻¹) (smulRight (1 : 𝕜 →L[𝕜] 𝕜) (-(x ^ 2)⁻¹) : 𝕜 →L[𝕜] 𝕜) s x := (hasFDerivAt_inv x_ne_zero).hasFDerivWithinAt @@ -101,7 +98,7 @@ theorem fderiv_inv : fderiv 𝕜 (fun x => x⁻¹) x = smulRight (1 : 𝕜 →L[ theorem fderivWithin_inv (x_ne_zero : x ≠ 0) (hxs : UniqueDiffWithinAt 𝕜 s x) : fderivWithin 𝕜 (fun x => x⁻¹) s x = smulRight (1 : 𝕜 →L[𝕜] 𝕜) (-(x ^ 2)⁻¹) := by - rw [DifferentiableAt.fderivWithin (differentiableAt_inv.2 x_ne_zero) hxs] + rw [DifferentiableAt.fderivWithin (differentiableAt_inv x_ne_zero) hxs] exact fderiv_inv variable {c : 𝕜 → 𝕜} {h : E → 𝕜} {c' : 𝕜} {z : E} {S : Set E} @@ -116,22 +113,6 @@ theorem HasDerivAt.inv (hc : HasDerivAt c c' x) (hx : c x ≠ 0) : rw [← hasDerivWithinAt_univ] at * exact hc.inv hx -theorem DifferentiableWithinAt.inv (hf : DifferentiableWithinAt 𝕜 h S z) (hz : h z ≠ 0) : - DifferentiableWithinAt 𝕜 (fun x => (h x)⁻¹) S z := - (differentiableAt_inv.mpr hz).comp_differentiableWithinAt z hf - -@[simp] -theorem DifferentiableAt.inv (hf : DifferentiableAt 𝕜 h z) (hz : h z ≠ 0) : - DifferentiableAt 𝕜 (fun x => (h x)⁻¹) z := - (differentiableAt_inv.mpr hz).comp z hf - -theorem DifferentiableOn.inv (hf : DifferentiableOn 𝕜 h S) (hz : ∀ x ∈ S, h x ≠ 0) : - DifferentiableOn 𝕜 (fun x => (h x)⁻¹) S := fun x h => (hf x h).inv (hz x h) - -@[simp] -theorem Differentiable.inv (hf : Differentiable 𝕜 h) (hz : ∀ x, h x ≠ 0) : - Differentiable 𝕜 fun x => (h x)⁻¹ := fun x => (hf x).inv (hz x) - theorem derivWithin_inv' (hc : DifferentiableWithinAt 𝕜 c s x) (hx : c x ≠ 0) (hxs : UniqueDiffWithinAt 𝕜 s x) : derivWithin (fun x => (c x)⁻¹) s x = -derivWithin c s x / c x ^ 2 := diff --git a/Mathlib/Analysis/Calculus/DiffContOnCl.lean b/Mathlib/Analysis/Calculus/DiffContOnCl.lean index 10a6fd3b0a289..03f7ad0b9609c 100644 --- a/Mathlib/Analysis/Calculus/DiffContOnCl.lean +++ b/Mathlib/Analysis/Calculus/DiffContOnCl.lean @@ -3,8 +3,9 @@ Copyright (c) 2022 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Analysis.Calculus.Deriv.Inv import Mathlib.Analysis.NormedSpace.Real +import Mathlib.Analysis.Calculus.FDeriv.Add +import Mathlib.Analysis.Calculus.FDeriv.Mul /-! # Functions differentiable on a domain and continuous on its closure diff --git a/Mathlib/Analysis/Calculus/Dslope.lean b/Mathlib/Analysis/Calculus/Dslope.lean index a35fb76d7fa45..df304274fc2ac 100644 --- a/Mathlib/Analysis/Calculus/Dslope.lean +++ b/Mathlib/Analysis/Calculus/Dslope.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Analysis.Calculus.Deriv.Slope -import Mathlib.Analysis.Calculus.Deriv.Inv +import Mathlib.Analysis.Calculus.Deriv.Comp +import Mathlib.Analysis.Calculus.FDeriv.Add +import Mathlib.Analysis.Calculus.FDeriv.Mul /-! # Slope of a differentiable function diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 328fdab8161af..ef38ec6312a71 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -58,6 +58,12 @@ theorem HasFPowerSeriesAt.fderiv_eq (h : HasFPowerSeriesAt f p x) : fderiv 𝕜 f x = continuousMultilinearCurryFin1 𝕜 E F (p 1) := h.hasFDerivAt.fderiv +theorem AnalyticAt.hasStrictFDerivAt (h : AnalyticAt 𝕜 f x) : + HasStrictFDerivAt f (fderiv 𝕜 f x) x := by + rcases h with ⟨p, hp⟩ + rw [hp.fderiv_eq] + exact hp.hasStrictFDerivAt + theorem HasFPowerSeriesOnBall.differentiableOn [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) : DifferentiableOn 𝕜 f (EMetric.ball x r) := fun _ hy => (h.analyticAt_of_mem hy).differentiableWithinAt diff --git a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean index 47dd475da18fc..d867ef086d9c7 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean @@ -3,6 +3,8 @@ Copyright (c) 2019 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Sébastien Gouëzel, Yury Kudryashov -/ +import Mathlib.Analysis.Analytic.Constructions +import Mathlib.Analysis.Calculus.FDeriv.Analytic import Mathlib.Analysis.Calculus.FDeriv.Bilinear /-! @@ -775,16 +777,15 @@ end Prod section AlgebraInverse -variable {R : Type*} [NormedRing R] [NormedAlgebra 𝕜 R] [CompleteSpace R] +variable {R : Type*} [NormedRing R] [HasSummableGeomSeries R] [NormedAlgebra 𝕜 R] open NormedRing ContinuousLinearMap Ring /-- At an invertible element `x` of a normed algebra `R`, the Fréchet derivative of the inversion operation is the linear map `fun t ↦ - x⁻¹ * t * x⁻¹`. -TODO: prove that `Ring.inverse` is analytic and use it to prove a `HasStrictFDerivAt` lemma. -TODO (low prio): prove a version without assumption `[CompleteSpace R]` but within the set of -units. -/ +TODO (low prio): prove a version without assumption `[HasSummableGeomSeries R]` but within the set +of units. -/ @[fun_prop] theorem hasFDerivAt_ring_inverse (x : Rˣ) : HasFDerivAt Ring.inverse (-mulLeftRight 𝕜 R ↑x⁻¹ ↑x⁻¹) x := @@ -809,6 +810,11 @@ theorem differentiableOn_inverse : DifferentiableOn 𝕜 (@Ring.inverse R _) {x theorem fderiv_inverse (x : Rˣ) : fderiv 𝕜 (@Ring.inverse R _) x = -mulLeftRight 𝕜 R ↑x⁻¹ ↑x⁻¹ := (hasFDerivAt_ring_inverse x).fderiv +theorem hasStrictFDerivAt_ring_inverse (x : Rˣ) : + HasStrictFDerivAt Ring.inverse (-mulLeftRight 𝕜 R ↑x⁻¹ ↑x⁻¹) x := by + convert (analyticAt_inverse (𝕜 := 𝕜) x).hasStrictFDerivAt + exact (fderiv_inverse x).symm + variable {h : E → R} {z : E} {S : Set E} @[fun_prop] @@ -833,35 +839,51 @@ end AlgebraInverse /-! ### Derivative of the inverse in a division ring -Note these lemmas are primed as they need `CompleteSpace R`, whereas the other lemmas in -`Mathlib/Analysis/Calculus/Deriv/Inv.lean` do not, but instead need `NontriviallyNormedField R`. +Note that some lemmas are primed as they are expressed without commutativity, whereas their +counterparts in commutative fields involve simpler expressions, and are given in +`Mathlib/Analysis/Calculus/Deriv/Inv.lean`. -/ section DivisionRingInverse -variable {R : Type*} [NormedDivisionRing R] [NormedAlgebra 𝕜 R] [CompleteSpace R] +variable {R : Type*} [NormedDivisionRing R] [NormedAlgebra 𝕜 R] open NormedRing ContinuousLinearMap Ring +/-- At an invertible element `x` of a normed division algebra `R`, the inversion is strictly +differentiable, with derivative the linear map `fun t ↦ - x⁻¹ * t * x⁻¹`. For a nicer formula in +the commutative case, see `hasStrictFDerivAt_inv`. -/ +theorem hasStrictFDerivAt_inv' {x : R} (hx : x ≠ 0) : + HasStrictFDerivAt Inv.inv (-mulLeftRight 𝕜 R x⁻¹ x⁻¹) x := by + simpa using hasStrictFDerivAt_ring_inverse (Units.mk0 _ hx) + /-- At an invertible element `x` of a normed division algebra `R`, the Fréchet derivative of the -inversion operation is the linear map `fun t ↦ - x⁻¹ * t * x⁻¹`. -/ +inversion operation is the linear map `fun t ↦ - x⁻¹ * t * x⁻¹`. For a nicer formula in the +commutative case, see `hasFDerivAt_inv`. -/ @[fun_prop] theorem hasFDerivAt_inv' {x : R} (hx : x ≠ 0) : HasFDerivAt Inv.inv (-mulLeftRight 𝕜 R x⁻¹ x⁻¹) x := by simpa using hasFDerivAt_ring_inverse (Units.mk0 _ hx) @[fun_prop] -theorem differentiableAt_inv' {x : R} (hx : x ≠ 0) : DifferentiableAt 𝕜 Inv.inv x := +theorem differentiableAt_inv {x : R} (hx : x ≠ 0) : DifferentiableAt 𝕜 Inv.inv x := (hasFDerivAt_inv' hx).differentiableAt +@[deprecated (since := "2024-09-21")] alias differentiableAt_inv' := differentiableAt_inv + @[fun_prop] -theorem differentiableWithinAt_inv' {x : R} (hx : x ≠ 0) (s : Set R) : +theorem differentiableWithinAt_inv {x : R} (hx : x ≠ 0) (s : Set R) : DifferentiableWithinAt 𝕜 (fun x => x⁻¹) s x := - (differentiableAt_inv' hx).differentiableWithinAt + (differentiableAt_inv hx).differentiableWithinAt + +@[deprecated (since := "2024-09-21")] +alias differentiableWithinAt_inv' := differentiableWithinAt_inv @[fun_prop] -theorem differentiableOn_inv' : DifferentiableOn 𝕜 (fun x : R => x⁻¹) {x | x ≠ 0} := fun _x hx => - differentiableWithinAt_inv' hx _ +theorem differentiableOn_inv : DifferentiableOn 𝕜 (fun x : R => x⁻¹) {x | x ≠ 0} := fun _x hx => + differentiableWithinAt_inv hx _ + +@[deprecated (since := "2024-09-21")] alias differentiableOn_inv' := differentiableOn_inv /-- Non-commutative version of `fderiv_inv` -/ theorem fderiv_inv' {x : R} (hx : x ≠ 0) : fderiv 𝕜 Inv.inv x = -mulLeftRight 𝕜 R x⁻¹ x⁻¹ := @@ -870,28 +892,37 @@ theorem fderiv_inv' {x : R} (hx : x ≠ 0) : fderiv 𝕜 Inv.inv x = -mulLeftRig /-- Non-commutative version of `fderivWithin_inv` -/ theorem fderivWithin_inv' {s : Set R} {x : R} (hx : x ≠ 0) (hxs : UniqueDiffWithinAt 𝕜 s x) : fderivWithin 𝕜 (fun x => x⁻¹) s x = -mulLeftRight 𝕜 R x⁻¹ x⁻¹ := by - rw [DifferentiableAt.fderivWithin (differentiableAt_inv' hx) hxs] + rw [DifferentiableAt.fderivWithin (differentiableAt_inv hx) hxs] exact fderiv_inv' hx variable {h : E → R} {z : E} {S : Set E} @[fun_prop] -theorem DifferentiableWithinAt.inv' (hf : DifferentiableWithinAt 𝕜 h S z) (hz : h z ≠ 0) : +theorem DifferentiableWithinAt.inv (hf : DifferentiableWithinAt 𝕜 h S z) (hz : h z ≠ 0) : DifferentiableWithinAt 𝕜 (fun x => (h x)⁻¹) S z := - (differentiableAt_inv' hz).comp_differentiableWithinAt z hf + (differentiableAt_inv hz).comp_differentiableWithinAt z hf + +@[deprecated (since := "2024-09-21")] +alias DifferentiableWithinAt.inv' := DifferentiableWithinAt.inv @[simp, fun_prop] -theorem DifferentiableAt.inv' (hf : DifferentiableAt 𝕜 h z) (hz : h z ≠ 0) : +theorem DifferentiableAt.inv (hf : DifferentiableAt 𝕜 h z) (hz : h z ≠ 0) : DifferentiableAt 𝕜 (fun x => (h x)⁻¹) z := - (differentiableAt_inv' hz).comp z hf + (differentiableAt_inv hz).comp z hf + +@[deprecated (since := "2024-09-21")] alias DifferentiableAt.inv' := DifferentiableAt.inv @[fun_prop] -theorem DifferentiableOn.inv' (hf : DifferentiableOn 𝕜 h S) (hz : ∀ x ∈ S, h x ≠ 0) : - DifferentiableOn 𝕜 (fun x => (h x)⁻¹) S := fun x h => (hf x h).inv' (hz x h) +theorem DifferentiableOn.inv (hf : DifferentiableOn 𝕜 h S) (hz : ∀ x ∈ S, h x ≠ 0) : + DifferentiableOn 𝕜 (fun x => (h x)⁻¹) S := fun x h => (hf x h).inv (hz x h) + +@[deprecated (since := "2024-09-21")] alias DifferentiableOn.inv' := DifferentiableOn.inv @[simp, fun_prop] -theorem Differentiable.inv' (hf : Differentiable 𝕜 h) (hz : ∀ x, h x ≠ 0) : - Differentiable 𝕜 fun x => (h x)⁻¹ := fun x => (hf x).inv' (hz x) +theorem Differentiable.inv (hf : Differentiable 𝕜 h) (hz : ∀ x, h x ≠ 0) : + Differentiable 𝕜 fun x => (h x)⁻¹ := fun x => (hf x).inv (hz x) + +@[deprecated (since := "2024-09-21")] alias Differentiable.inv' := Differentiable.inv end DivisionRingInverse diff --git a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean index 6bdbec8adca03..f967929332fbd 100644 --- a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean +++ b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean @@ -272,7 +272,7 @@ variable (𝕜) /-- In a Banach algebra `A` over a nontrivially normed field `𝕜`, for any `a : A` the power series with coefficients `a ^ n` represents the function `(1 - z • a)⁻¹` in a disk of radius `‖a‖₊⁻¹`. -/ -theorem hasFPowerSeriesOnBall_inverse_one_sub_smul [CompleteSpace A] (a : A) : +theorem hasFPowerSeriesOnBall_inverse_one_sub_smul [HasSummableGeomSeries A] (a : A) : HasFPowerSeriesOnBall (fun z : 𝕜 => Ring.inverse (1 - z • a)) (fun n => ContinuousMultilinearMap.mkPiRing 𝕜 (Fin n) (a ^ n)) 0 ‖a‖₊⁻¹ := { r_le := by @@ -297,7 +297,7 @@ theorem hasFPowerSeriesOnBall_inverse_one_sub_smul [CompleteSpace A] (a : A) : simpa only [← coe_inv h, mem_ball_zero_iff, Metric.emetric_ball_nnreal] using hy rwa [← coe_nnnorm, ← Real.lt_toNNReal_iff_coe_lt, Real.toNNReal_one, nnnorm_smul, ← NNReal.lt_inv_iff_mul_lt h] - simpa [← smul_pow, (NormedRing.summable_geometric_of_norm_lt_one _ norm_lt).hasSum_iff] using + simpa [← smul_pow, (summable_geometric_of_norm_lt_one norm_lt).hasSum_iff] using (NormedRing.inverse_one_sub _ norm_lt).symm } variable {𝕜} diff --git a/Mathlib/Analysis/Normed/Ring/Units.lean b/Mathlib/Analysis/Normed/Ring/Units.lean index a99777748c99d..6a9faca97ff80 100644 --- a/Mathlib/Analysis/Normed/Ring/Units.lean +++ b/Mathlib/Analysis/Normed/Ring/Units.lean @@ -14,12 +14,12 @@ normed ring (Banach algebras being a notable special case). ## Main results -The constructions `Units.oneSub`, `Units.add`, and `Units.ofNearby` state, in varying forms, that -perturbations of a unit are units. The latter two are not stated in their optimal form; more precise -versions would use the spectral radius. +The constructions `Units.add` and `Units.ofNearby` (based on `Units.oneSub` defined elsewhere) +state, in varying forms, that perturbations of a unit are units. They are not stated +in their optimal form; more precise versions would use the spectral radius. -The first main result is `Units.isOpen`: the group of units of a complete normed ring is an open -subset of the ring. +The first main result is `Units.isOpen`: the group of units of a normed ring with summable +geometric series is an open subset of the ring. The function `Ring.inverse` (defined elsewhere), for a ring `R`, sends `a : R` to `a⁻¹` if `a` is a unit and `0` if not. The other major results of this file (notably `NormedRing.inverse_add`, @@ -31,21 +31,13 @@ noncomputable section open Topology -variable {R : Type*} [NormedRing R] [CompleteSpace R] +variable {R : Type*} [NormedRing R] [HasSummableGeomSeries R] namespace Units -/-- In a complete normed ring, a perturbation of `1` by an element `t` of distance less than `1` -from `1` is a unit. Here we construct its `Units` structure. -/ -@[simps val] -def oneSub (t : R) (h : ‖t‖ < 1) : Rˣ where - val := 1 - t - inv := ∑' n : ℕ, t ^ n - val_inv := mul_neg_geom_series t h - inv_val := geom_series_mul_neg t h - -/-- In a complete normed ring, a perturbation of a unit `x` by an element `t` of distance less than -`‖x⁻¹‖⁻¹` from `x` is a unit. Here we construct its `Units` structure. -/ +/-- In a normed ring with summable geometric series, a perturbation of a unit `x` by an +element `t` of distance less than `‖x⁻¹‖⁻¹` from `x` is a unit. +Here we construct its `Units` structure. -/ @[simps! val] def add (x : Rˣ) (t : R) (h : ‖t‖ < ‖(↑x⁻¹ : R)‖⁻¹) : Rˣ := Units.copy -- to make `add_val` true definitionally, for convenience @@ -59,13 +51,14 @@ def add (x : Rˣ) (t : R) (h : ‖t‖ < ‖(↑x⁻¹ : R)‖⁻¹) : Rˣ := _ = 1 := mul_inv_cancel₀ (ne_of_gt hpos))) (x + t) (by simp [mul_add]) _ rfl -/-- In a complete normed ring, an element `y` of distance less than `‖x⁻¹‖⁻¹` from `x` is a unit. -Here we construct its `Units` structure. -/ +/-- In a normed ring with summable geometric series, an element `y` of distance less +than `‖x⁻¹‖⁻¹` from `x` is a unit. Here we construct its `Units` structure. -/ @[simps! val] def ofNearby (x : Rˣ) (y : R) (h : ‖y - x‖ < ‖(↑x⁻¹ : R)‖⁻¹) : Rˣ := (x.add (y - x : R) h).copy y (by simp) _ rfl -/-- The group of units of a complete normed ring is an open subset of the ring. -/ +/-- The group of units of a normed ring with summable geometric series is an open subset +of the ring. -/ protected theorem isOpen : IsOpen { x : R | IsUnit x } := by nontriviality R rw [Metric.isOpen_iff] @@ -81,12 +74,12 @@ end Units namespace nonunits -/-- The `nonunits` in a complete normed ring are contained in the complement of the ball of radius -`1` centered at `1 : R`. -/ +/-- The `nonunits` in a normed ring with summable geometric series are contained in the +complement of the ball of radius `1` centered at `1 : R`. -/ theorem subset_compl_ball : nonunits R ⊆ (Metric.ball (1 : R) 1)ᶜ := fun x hx h₁ ↦ hx <| sub_sub_self 1 x ▸ (Units.oneSub (1 - x) (by rwa [mem_ball_iff_norm'] at h₁)).isUnit --- The `nonunits` in a complete normed ring are a closed set +-- The `nonunits` in a normed ring with summable geometric series are a closed set protected theorem isClosed : IsClosed (nonunits R) := Units.isOpen.isClosed_compl @@ -114,7 +107,7 @@ theorem inverse_add (x : Rˣ) : theorem inverse_one_sub_nth_order' (n : ℕ) {t : R} (ht : ‖t‖ < 1) : inverse ((1 : R) - t) = (∑ i ∈ range n, t ^ i) + t ^ n * inverse (1 - t) := - have := NormedRing.summable_geometric_of_norm_lt_one t ht + have := _root_.summable_geometric_of_norm_lt_one ht calc inverse (1 - t) = ∑' i : ℕ, t ^ i := inverse_one_sub t ht _ = ∑ i ∈ range n, t ^ i + ∑' i : ℕ, t ^ (i + n) := (sum_add_tsum_nat_add _ this).symm _ = (∑ i ∈ range n, t ^ i) + t ^ n * inverse (1 - t) := by @@ -149,7 +142,7 @@ theorem inverse_one_sub_norm : (fun t : R => inverse (1 - t)) =O[𝓝 0] (fun _t linarith simp only [inverse_one_sub t ht', norm_one, mul_one, Set.mem_setOf_eq] change ‖∑' n : ℕ, t ^ n‖ ≤ _ - have := NormedRing.tsum_geometric_of_norm_lt_one t ht' + have := tsum_geometric_le_of_norm_lt_one t ht' have : (1 - ‖t‖)⁻¹ ≤ 2 := by rw [← inv_inv (2 : ℝ)] refine inv_le_inv_of_le (by norm_num) ?_ @@ -205,15 +198,15 @@ namespace Units open MulOpposite Filter NormedRing -/-- In a normed ring, the coercion from `Rˣ` (equipped with the induced topology from the -embedding in `R × R`) to `R` is an open embedding. -/ +/-- In a normed ring with summable geometric series, the coercion from `Rˣ` (equipped with the +induced topology from the embedding in `R × R`) to `R` is an open embedding. -/ theorem openEmbedding_val : OpenEmbedding (val : Rˣ → R) where toEmbedding := embedding_val_mk' (fun _ ⟨u, hu⟩ ↦ hu ▸ (inverse_continuousAt u).continuousWithinAt) Ring.inverse_unit isOpen_range := Units.isOpen -/-- In a normed ring, the coercion from `Rˣ` (equipped with the induced topology from the -embedding in `R × R`) to `R` is an open map. -/ +/-- In a normed ring with summable geometric series, the coercion from `Rˣ` (equipped with the +induced topology from the embedding in `R × R`) to `R` is an open map. -/ theorem isOpenMap_val : IsOpenMap (val : Rˣ → R) := openEmbedding_val.isOpenMap @@ -227,16 +220,18 @@ theorem eq_top_of_norm_lt_one (I : Ideal R) {x : R} (hxI : x ∈ I) (hx : ‖1 - I.eq_top_iff_one.mpr <| by simpa only [show u.inv * x = 1 by simp [u]] using I.mul_mem_left u.inv hxI -/-- The `Ideal.closure` of a proper ideal in a complete normed ring is proper. -/ +/-- The `Ideal.closure` of a proper ideal in a normed ring with summable +geometric series is proper. -/ theorem closure_ne_top (I : Ideal R) (hI : I ≠ ⊤) : I.closure ≠ ⊤ := by have h := closure_minimal (coe_subset_nonunits hI) nonunits.isClosed simpa only [I.closure.eq_top_iff_one, Ne] using mt (@h 1) one_not_mem_nonunits -/-- The `Ideal.closure` of a maximal ideal in a complete normed ring is the ideal itself. -/ +/-- The `Ideal.closure` of a maximal ideal in a normed ring with summable +geometric series is the ideal itself. -/ theorem IsMaximal.closure_eq {I : Ideal R} (hI : I.IsMaximal) : I.closure = I := (hI.eq_of_le (I.closure_ne_top hI.ne_top) subset_closure).symm -/-- Maximal ideals in complete normed rings are closed. -/ +/-- Maximal ideals in normed rings with summable geometric series are closed. -/ instance IsMaximal.isClosed {I : Ideal R} [hI : I.IsMaximal] : IsClosed (I : Set R) := isClosed_of_closure_subset <| Eq.subset <| congr_arg ((↑) : Ideal R → Set R) hI.closure_eq diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index 1cc64031c7c79..8c50769ed4fbd 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -763,6 +763,12 @@ theorem norm_mkPiAlgebraFin_zero : ‖ContinuousMultilinearMap.mkPiAlgebraFin · convert ratio_le_opNorm (ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 0 A) fun _ => (1 : A) simp +theorem norm_mkPiAlgebraFin_le : + ‖ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 n A‖ ≤ max 1 ‖(1 : A)‖ := by + cases n + · exact norm_mkPiAlgebraFin_zero.le.trans (le_max_right _ _) + · exact (norm_mkPiAlgebraFin_le_of_pos (Nat.zero_lt_succ _)).trans (le_max_left _ _) + @[simp] theorem norm_mkPiAlgebraFin [NormOneClass A] : ‖ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 n A‖ = 1 := by diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index d15e75afada5e..a84b941a538ea 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -20,19 +20,13 @@ import Mathlib.Tactic.NoncommRing This file contains important specific limit computations in (semi-)normed groups/rings/spaces, as well as such computations in `ℝ` when the natural proof passes through a fact about normed spaces. - -/ - noncomputable section -open scoped Classical -open Set Function Filter Finset Metric Asymptotics +open Set Function Filter Finset Metric Asymptotics Topology Nat NNReal ENNReal -open scoped Classical -open Topology Nat uniformity NNReal ENNReal - -variable {α : Type*} {β : Type*} {ι : Type*} +variable {α β ι : Type*} theorem tendsto_norm_atTop_atTop : Tendsto (norm : ℝ → ℝ) atTop atTop := tendsto_abs_atTop_atTop @@ -255,6 +249,113 @@ alias tendsto_pow_atTop_nhds_0_of_abs_lt_1 := tendsto_pow_atTop_nhds_zero_of_abs /-! ### Geometric series -/ +/-- A normed ring has summable geometric series if, for all `ξ` of norm `< 1`, the geometric series +`∑ ξ ^ n` converges. This holds both in complete normed rings and in normed fields, providing a +convenient abstraction of these two classes to avoid repeating the same proofs. -/ +class HasSummableGeomSeries (K : Type*) [NormedRing K] : Prop := + summable_geometric_of_norm_lt_one : ∀ (ξ : K), ‖ξ‖ < 1 → Summable (fun n ↦ ξ ^ n) + +lemma summable_geometric_of_norm_lt_one {K : Type*} [NormedRing K] [HasSummableGeomSeries K] + {x : K} (h : ‖x‖ < 1) : Summable (fun n ↦ x ^ n) := + HasSummableGeomSeries.summable_geometric_of_norm_lt_one x h + +instance {R : Type*} [NormedRing R] [CompleteSpace R] : HasSummableGeomSeries R := by + constructor + intro x hx + have h1 : Summable fun n : ℕ ↦ ‖x‖ ^ n := summable_geometric_of_lt_one (norm_nonneg _) hx + exact h1.of_norm_bounded_eventually_nat _ (eventually_norm_pow_le x) + +section HasSummableGeometricSeries + +variable {R : Type*} [NormedRing R] + +open NormedSpace + +/-- Bound for the sum of a geometric series in a normed ring. This formula does not assume that the +normed ring satisfies the axiom `‖1‖ = 1`. -/ +theorem tsum_geometric_le_of_norm_lt_one (x : R) (h : ‖x‖ < 1) : + ‖∑' n : ℕ, x ^ n‖ ≤ ‖(1 : R)‖ - 1 + (1 - ‖x‖)⁻¹ := by + by_cases hx : Summable (fun n ↦ x ^ n) + · rw [tsum_eq_zero_add hx] + simp only [_root_.pow_zero] + refine le_trans (norm_add_le _ _) ?_ + have : ‖∑' b : ℕ, (fun n ↦ x ^ (n + 1)) b‖ ≤ (1 - ‖x‖)⁻¹ - 1 := by + refine tsum_of_norm_bounded ?_ fun b ↦ norm_pow_le' _ (Nat.succ_pos b) + convert (hasSum_nat_add_iff' 1).mpr (hasSum_geometric_of_lt_one (norm_nonneg x) h) + simp + linarith + · simp [tsum_eq_zero_of_not_summable hx] + nontriviality R + have : 1 ≤ ‖(1 : R)‖ := one_le_norm_one R + have : 0 ≤ (1 - ‖x‖) ⁻¹ := inv_nonneg.2 (by linarith) + linarith + +variable [HasSummableGeomSeries R] + +@[deprecated (since := "2024-01-31")] +alias NormedRing.tsum_geometric_of_norm_lt_1 := tsum_geometric_le_of_norm_lt_one + +@[deprecated (since := "2024-07-27")] +alias NormedRing.tsum_geometric_of_norm_lt_one := tsum_geometric_le_of_norm_lt_one + +theorem geom_series_mul_neg (x : R) (h : ‖x‖ < 1) : (∑' i : ℕ, x ^ i) * (1 - x) = 1 := by + have := (summable_geometric_of_norm_lt_one h).hasSum.mul_right (1 - x) + refine tendsto_nhds_unique this.tendsto_sum_nat ?_ + have : Tendsto (fun n : ℕ ↦ 1 - x ^ n) atTop (𝓝 1) := by + simpa using tendsto_const_nhds.sub (tendsto_pow_atTop_nhds_zero_of_norm_lt_one h) + convert← this + rw [← geom_sum_mul_neg, Finset.sum_mul] + +theorem mul_neg_geom_series (x : R) (h : ‖x‖ < 1) : (1 - x) * ∑' i : ℕ, x ^ i = 1 := by + have := (summable_geometric_of_norm_lt_one h).hasSum.mul_left (1 - x) + refine tendsto_nhds_unique this.tendsto_sum_nat ?_ + have : Tendsto (fun n : ℕ ↦ 1 - x ^ n) atTop (𝓝 1) := by + simpa using tendsto_const_nhds.sub (tendsto_pow_atTop_nhds_zero_of_norm_lt_one h) + convert← this + rw [← mul_neg_geom_sum, Finset.mul_sum] + +theorem geom_series_succ (x : R) (h : ‖x‖ < 1) : ∑' i : ℕ, x ^ (i + 1) = ∑' i : ℕ, x ^ i - 1 := by + rw [eq_sub_iff_add_eq, tsum_eq_zero_add (summable_geometric_of_norm_lt_one h), + pow_zero, add_comm] + +theorem geom_series_mul_shift (x : R) (h : ‖x‖ < 1) : + x * ∑' i : ℕ, x ^ i = ∑' i : ℕ, x ^ (i + 1) := by + simp_rw [← (summable_geometric_of_norm_lt_one h).tsum_mul_left, ← _root_.pow_succ'] + +theorem geom_series_mul_one_add (x : R) (h : ‖x‖ < 1) : + (1 + x) * ∑' i : ℕ, x ^ i = 2 * ∑' i : ℕ, x ^ i - 1 := by + rw [add_mul, one_mul, geom_series_mul_shift x h, geom_series_succ x h, two_mul, add_sub_assoc] + +/-- In a normed ring with summable geometric series, a perturbation of `1` by an element `t` +of distance less than `1` from `1` is a unit. Here we construct its `Units` structure. -/ +@[simps val] +def Units.oneSub (t : R) (h : ‖t‖ < 1) : Rˣ where + val := 1 - t + inv := ∑' n : ℕ, t ^ n + val_inv := mul_neg_geom_series t h + inv_val := geom_series_mul_neg t h + +theorem geom_series_eq_inverse (x : R) (h : ‖x‖ < 1) : + ∑' i, x ^ i = Ring.inverse (1 - x) := by + change (Units.oneSub x h) ⁻¹ = Ring.inverse (1 - x) + rw [← Ring.inverse_unit] + rfl + +theorem hasSum_geom_series_inverse (x : R) (h : ‖x‖ < 1) : + HasSum (fun i ↦ x ^ i) (Ring.inverse (1 - x)) := by + convert (summable_geometric_of_norm_lt_one h).hasSum + exact (geom_series_eq_inverse x h).symm + +lemma isUnit_one_sub_of_norm_lt_one {x : R} (h : ‖x‖ < 1) : IsUnit (1 - x) := + ⟨Units.oneSub x h, rfl⟩ + +end HasSummableGeometricSeries + +@[deprecated (since := "2024-01-31")] +alias NormedRing.summable_geometric_of_norm_lt_1 := summable_geometric_of_norm_lt_one + +@[deprecated (since := "2024-07-27")] +alias NormedRing.summable_geometric_of_norm_lt_one := summable_geometric_of_norm_lt_one section Geometric @@ -273,8 +374,8 @@ theorem hasSum_geometric_of_norm_lt_one (h : ‖ξ‖ < 1) : HasSum (fun n : ℕ @[deprecated (since := "2024-01-31")] alias hasSum_geometric_of_norm_lt_1 := hasSum_geometric_of_norm_lt_one -theorem summable_geometric_of_norm_lt_one (h : ‖ξ‖ < 1) : Summable fun n : ℕ ↦ ξ ^ n := - ⟨_, hasSum_geometric_of_norm_lt_one h⟩ +instance : HasSummableGeomSeries K := + ⟨fun _ h ↦ (hasSum_geometric_of_norm_lt_one h).summable⟩ @[deprecated (since := "2024-01-31")] alias summable_geometric_of_norm_lt_1 := summable_geometric_of_norm_lt_one @@ -322,7 +423,9 @@ end Geometric section MulGeometric -theorem summable_norm_mul_geometric_of_norm_lt_one {R : Type*} [NormedRing R] {k : ℕ} {r : R} +variable {R : Type*} [NormedRing R] {𝕜 : Type*} [NormedDivisionRing 𝕜] + +theorem summable_norm_mul_geometric_of_norm_lt_one {k : ℕ} {r : R} (hr : ‖r‖ < 1) {u : ℕ → ℕ} (hu : (fun n ↦ (u n : ℝ)) =O[atTop] (fun n ↦ (↑(n ^ k) : ℝ))) : Summable fun n : ℕ ↦ ‖(u n * r ^ n : R)‖ := by rcases exists_between hr with ⟨r', hrr', h⟩ @@ -337,35 +440,29 @@ theorem summable_norm_mul_geometric_of_norm_lt_one {R : Type*} [NormedRing R] {k apply (norm_mul_le _ _).trans have : ‖(u n : R)‖ * ‖r ^ n‖ ≤ (u n * ‖(1 : R)‖) * ‖r‖ ^ n := by gcongr; exact norm_cast_le (u n) - exact this.trans_eq (by ring) + exact this.trans (le_of_eq (by ring)) _ =O[atTop] fun n ↦ ↑(n ^ k) * ‖r‖ ^ n := hu.mul (isBigO_refl _ _) _ =O[atTop] fun n ↦ r' ^ n := by simp only [cast_pow] exact (isLittleO_pow_const_mul_const_pow_const_pow_of_norm_lt k hrr').isBigO -theorem summable_norm_pow_mul_geometric_of_norm_lt_one {R : Type*} [NormedRing R] (k : ℕ) {r : R} +theorem summable_norm_pow_mul_geometric_of_norm_lt_one (k : ℕ) {r : R} (hr : ‖r‖ < 1) : Summable fun n : ℕ ↦ ‖((n : R) ^ k * r ^ n : R)‖ := by simp only [← cast_pow] exact summable_norm_mul_geometric_of_norm_lt_one (k := k) (u := fun n ↦ n ^ k) hr (isBigO_refl _ _) -theorem summable_norm_geometric_of_norm_lt_one {R : Type*} [NormedRing R] {r : R} +theorem summable_norm_geometric_of_norm_lt_one {r : R} (hr : ‖r‖ < 1) : Summable fun n : ℕ ↦ ‖(r ^ n : R)‖ := by simpa using summable_norm_pow_mul_geometric_of_norm_lt_one 0 hr -@[deprecated (since := "2024-01-31")] -alias summable_norm_pow_mul_geometric_of_norm_lt_1 := summable_norm_pow_mul_geometric_of_norm_lt_one - -variable {𝕜 : Type*} [NormedDivisionRing 𝕜] +variable [HasSummableGeomSeries R] -/-- The sum of `(n+k).choose k * r^n` is `1/(1-r)^{k+1}`. -See also `PowerSeries.invOneSubPow_val_eq_mk_choose_add` for the corresponding statement in formal -power series, without summability arguments. -/ -lemma hasSum_choose_mul_geometric_of_norm_lt_one - (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : - HasSum (fun n ↦ (n + k).choose k * r ^ n) (1 / (1 - r) ^ (k + 1)) := by +lemma hasSum_choose_mul_geometric_of_norm_lt_one' + (k : ℕ) {r : R} (hr : ‖r‖ < 1) : + HasSum (fun n ↦ (n + k).choose k * r ^ n) (Ring.inverse (1 - r) ^ (k + 1)) := by induction k with - | zero => simpa using hasSum_geometric_of_norm_lt_one hr + | zero => simpa using hasSum_geom_series_inverse r hr | succ k ih => have I1 : Summable (fun (n : ℕ) ↦ ‖(n + k).choose k * r ^ n‖) := by apply summable_norm_mul_geometric_of_norm_lt_one (k := k) hr @@ -378,34 +475,42 @@ lemma hasSum_choose_mul_geometric_of_norm_lt_one _ ≤ (2 * n) ^ k := Nat.choose_le_pow _ _ _ = 2 ^ k * n ^ k := Nat.mul_pow 2 n k convert hasSum_sum_range_mul_of_summable_norm' I1 ih.summable - (summable_norm_geometric_of_norm_lt_one hr) (summable_geometric_of_norm_lt_one hr) using 1 - · ext n - have : ∑ i ∈ Finset.range (n + 1), ↑((i + k).choose k) * r ^ i * r ^ (n - i) = + (summable_norm_geometric_of_norm_lt_one hr) (summable_geometric_of_norm_lt_one hr) with n + · have : ∑ i ∈ Finset.range (n + 1), ↑((i + k).choose k) * r ^ i * r ^ (n - i) = ∑ i ∈ Finset.range (n + 1), ↑((i + k).choose k) * r ^ n := by apply Finset.sum_congr rfl (fun i hi ↦ ?_) simp only [Finset.mem_range] at hi rw [mul_assoc, ← pow_add, show i + (n - i) = n by omega] - simp_rw [this, ← sum_mul, ← Nat.cast_sum, sum_range_add_choose n k, add_assoc] - · rw [ih.tsum_eq, (hasSum_geometric_of_norm_lt_one hr).tsum_eq, pow_succ] - simp only [one_div, ← mul_inv_rev, ← pow_succ, ← _root_.pow_succ'] + simp [this, ← sum_mul, ← Nat.cast_sum, sum_range_add_choose n k, add_assoc] + · rw [ih.tsum_eq, (hasSum_geom_series_inverse r hr).tsum_eq, pow_succ] -lemma summable_choose_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : +lemma summable_choose_mul_geometric_of_norm_lt_one (k : ℕ) {r : R} (hr : ‖r‖ < 1) : Summable (fun n ↦ (n + k).choose k * r ^ n) := - (hasSum_choose_mul_geometric_of_norm_lt_one k hr).summable + (hasSum_choose_mul_geometric_of_norm_lt_one' k hr).summable + +lemma tsum_choose_mul_geometric_of_norm_lt_one' (k : ℕ) {r : R} (hr : ‖r‖ < 1) : + ∑' n, (n + k).choose k * r ^ n = (Ring.inverse (1 - r)) ^ (k + 1) := + (hasSum_choose_mul_geometric_of_norm_lt_one' k hr).tsum_eq + +lemma hasSum_choose_mul_geometric_of_norm_lt_one + (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : + HasSum (fun n ↦ (n + k).choose k * r ^ n) (1 / (1 - r) ^ (k + 1)) := by + convert hasSum_choose_mul_geometric_of_norm_lt_one' k hr + simp lemma tsum_choose_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : - ∑' n, (n + k).choose k * r ^ n = 1 / (1 - r) ^ (k + 1) := + ∑' n, (n + k).choose k * r ^ n = 1/ (1 - r) ^ (k + 1) := (hasSum_choose_mul_geometric_of_norm_lt_one k hr).tsum_eq -lemma summable_descFactorial_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : +lemma summable_descFactorial_mul_geometric_of_norm_lt_one (k : ℕ) {r : R} (hr : ‖r‖ < 1) : Summable (fun n ↦ (n + k).descFactorial k * r ^ n) := by - convert (summable_choose_mul_geometric_of_norm_lt_one k hr).mul_left (k.factorial : 𝕜) + convert (summable_choose_mul_geometric_of_norm_lt_one k hr).mul_left (k.factorial : R) using 2 with n simp [← mul_assoc, descFactorial_eq_factorial_mul_choose (n + k) k] open Polynomial in -theorem summable_pow_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : - Summable (fun n ↦ (n : 𝕜) ^ k * r ^ n : ℕ → 𝕜) := by +theorem summable_pow_mul_geometric_of_norm_lt_one (k : ℕ) {r : R} (hr : ‖r‖ < 1) : + Summable (fun n ↦ (n : R) ^ k * r ^ n : ℕ → R) := by refine Nat.strong_induction_on k fun k hk => ?_ obtain ⟨a, ha⟩ : ∃ (a : ℕ → ℕ), ∀ n, (n + k).descFactorial k = n ^ k + ∑ i ∈ range k, a i * n ^ i := by @@ -430,37 +535,50 @@ theorem summable_pow_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖ ext n simp [ha n, add_mul, sum_mul] +@[deprecated (since := "2024-01-31")] +alias summable_norm_pow_mul_geometric_of_norm_lt_1 := summable_norm_pow_mul_geometric_of_norm_lt_one + @[deprecated (since := "2024-01-31")] alias summable_pow_mul_geometric_of_norm_lt_1 := summable_pow_mul_geometric_of_norm_lt_one -/-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`, `HasSum` version. -/ -theorem hasSum_coe_mul_geometric_of_norm_lt_one - {r : 𝕜} (hr : ‖r‖ < 1) : HasSum (fun n ↦ n * r ^ n : ℕ → 𝕜) (r / (1 - r) ^ 2) := by - have A : HasSum (fun (n : ℕ) ↦ (n + 1) * r ^ n) (1 / (1 - r) ^ 2) := by - convert hasSum_choose_mul_geometric_of_norm_lt_one 1 hr with n +/-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`, `HasSum` version in a general ring +with summable geometric series. For a version in a field, using division instead of `Ring.inverse`, +see `hasSum_coe_mul_geometric_of_norm_lt_one`. -/ +theorem hasSum_coe_mul_geometric_of_norm_lt_one' + {x : R} (h : ‖x‖ < 1) : + HasSum (fun n ↦ n * x ^ n : ℕ → R) (x * (Ring.inverse (1 - x)) ^ 2) := by + have A : HasSum (fun (n : ℕ) ↦ (n + 1) * x ^ n) (Ring.inverse (1 - x) ^ 2) := by + convert hasSum_choose_mul_geometric_of_norm_lt_one' 1 h with n simp - have B : HasSum (fun (n : ℕ) ↦ r ^ n) ((1 - r) ⁻¹) := hasSum_geometric_of_norm_lt_one hr + have B : HasSum (fun (n : ℕ) ↦ x ^ n) (Ring.inverse (1 - x)) := hasSum_geom_series_inverse x h convert A.sub B using 1 · ext n simp [add_mul] · symm - calc 1 / (1 - r) ^ 2 - (1 - r) ⁻¹ - _ = 1 / (1 - r) ^ 2 - ((1 - r) * (1 - r) ⁻¹) * (1 - r) ⁻¹ := by - rw [mul_inv_cancel₀, one_mul] - intro h - simp only [sub_eq_zero] at h - simp [← h] at hr - _ = r / (1 - r) ^ 2 := by - simp only [one_div, mul_assoc, ← mul_inv_rev] - rw [inv_eq_one_div, inv_eq_one_div, ← pow_two, _root_.sub_mul, one_mul, mul_div, mul_one] - abel + calc Ring.inverse (1 - x) ^ 2 - Ring.inverse (1 - x) + _ = Ring.inverse (1 - x) ^ 2 - ((1 - x) * Ring.inverse (1 - x)) * Ring.inverse (1 - x) := by + simp [Ring.mul_inverse_cancel (1 - x) (isUnit_one_sub_of_norm_lt_one h)] + _ = x * Ring.inverse (1 - x) ^ 2 := by noncomm_ring + +/-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`, version in a general ring with +summable geometric series. For a version in a field, using division instead of `Ring.inverse`, +see `tsum_coe_mul_geometric_of_norm_lt_one`. -/ +theorem tsum_coe_mul_geometric_of_norm_lt_one' + {r : 𝕜} (hr : ‖r‖ < 1) : (∑' n : ℕ, n * r ^ n : 𝕜) = r * Ring.inverse (1 - r) ^ 2 := + (hasSum_coe_mul_geometric_of_norm_lt_one' hr).tsum_eq + +/-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`, `HasSum` version. -/ +theorem hasSum_coe_mul_geometric_of_norm_lt_one {r : 𝕜} (hr : ‖r‖ < 1) : + HasSum (fun n ↦ n * r ^ n : ℕ → 𝕜) (r / (1 - r) ^ 2) := by + convert hasSum_coe_mul_geometric_of_norm_lt_one' hr using 1 + simp [div_eq_mul_inv] @[deprecated (since := "2024-01-31")] alias hasSum_coe_mul_geometric_of_norm_lt_1 := hasSum_coe_mul_geometric_of_norm_lt_one /-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`. -/ -theorem tsum_coe_mul_geometric_of_norm_lt_one - {r : 𝕜} (hr : ‖r‖ < 1) : (∑' n : ℕ, n * r ^ n : 𝕜) = r / (1 - r) ^ 2 := +theorem tsum_coe_mul_geometric_of_norm_lt_one {r : 𝕜} (hr : ‖r‖ < 1) : + (∑' n : ℕ, n * r ^ n : 𝕜) = r / (1 - r) ^ 2 := (hasSum_coe_mul_geometric_of_norm_lt_one hr).tsum_eq @[deprecated (since := "2024-01-31")] @@ -544,67 +662,6 @@ lemma exists_norm_le_of_cauchySeq (h : CauchySeq fun n ↦ ∑ k ∈ range n, f end SummableLeGeometric -section NormedRingGeometric - -variable {R : Type*} [NormedRing R] [CompleteSpace R] - -open NormedSpace - -/-- A geometric series in a complete normed ring is summable. -Proved above (same name, different namespace) for not-necessarily-complete normed fields. -/ -theorem NormedRing.summable_geometric_of_norm_lt_one (x : R) (h : ‖x‖ < 1) : - Summable fun n : ℕ ↦ x ^ n := - have h1 : Summable fun n : ℕ ↦ ‖x‖ ^ n := summable_geometric_of_lt_one (norm_nonneg _) h - h1.of_norm_bounded_eventually_nat _ (eventually_norm_pow_le x) -@[deprecated (since := "2024-01-31")] -alias NormedRing.summable_geometric_of_norm_lt_1 := NormedRing.summable_geometric_of_norm_lt_one - -/-- Bound for the sum of a geometric series in a normed ring. This formula does not assume that the -normed ring satisfies the axiom `‖1‖ = 1`. -/ -theorem NormedRing.tsum_geometric_of_norm_lt_one (x : R) (h : ‖x‖ < 1) : - ‖∑' n : ℕ, x ^ n‖ ≤ ‖(1 : R)‖ - 1 + (1 - ‖x‖)⁻¹ := by - rw [tsum_eq_zero_add (summable_geometric_of_norm_lt_one x h)] - simp only [_root_.pow_zero] - refine le_trans (norm_add_le _ _) ?_ - have : ‖∑' b : ℕ, (fun n ↦ x ^ (n + 1)) b‖ ≤ (1 - ‖x‖)⁻¹ - 1 := by - refine tsum_of_norm_bounded ?_ fun b ↦ norm_pow_le' _ (Nat.succ_pos b) - convert (hasSum_nat_add_iff' 1).mpr (hasSum_geometric_of_lt_one (norm_nonneg x) h) - simp - linarith - -@[deprecated (since := "2024-01-31")] -alias NormedRing.tsum_geometric_of_norm_lt_1 := NormedRing.tsum_geometric_of_norm_lt_one - -theorem geom_series_mul_neg (x : R) (h : ‖x‖ < 1) : (∑' i : ℕ, x ^ i) * (1 - x) = 1 := by - have := (NormedRing.summable_geometric_of_norm_lt_one x h).hasSum.mul_right (1 - x) - refine tendsto_nhds_unique this.tendsto_sum_nat ?_ - have : Tendsto (fun n : ℕ ↦ 1 - x ^ n) atTop (𝓝 1) := by - simpa using tendsto_const_nhds.sub (tendsto_pow_atTop_nhds_zero_of_norm_lt_one h) - convert← this - rw [← geom_sum_mul_neg, Finset.sum_mul] - -theorem mul_neg_geom_series (x : R) (h : ‖x‖ < 1) : ((1 - x) * ∑' i : ℕ, x ^ i) = 1 := by - have := (NormedRing.summable_geometric_of_norm_lt_one x h).hasSum.mul_left (1 - x) - refine tendsto_nhds_unique this.tendsto_sum_nat ?_ - have : Tendsto (fun n : ℕ ↦ 1 - x ^ n) atTop (𝓝 1) := by - simpa using tendsto_const_nhds.sub (tendsto_pow_atTop_nhds_zero_of_norm_lt_one h) - convert← this - rw [← mul_neg_geom_sum, Finset.mul_sum] - -theorem geom_series_succ (x : R) (h : ‖x‖ < 1) : ∑' i : ℕ, x ^ (i + 1) = ∑' i : ℕ, x ^ i - 1 := by - rw [eq_sub_iff_add_eq, tsum_eq_zero_add (NormedRing.summable_geometric_of_norm_lt_one x h), - pow_zero, add_comm] - -theorem geom_series_mul_shift (x : R) (h : ‖x‖ < 1) : - x * ∑' i : ℕ, x ^ i = ∑' i : ℕ, x ^ (i + 1) := by - simp_rw [← (NormedRing.summable_geometric_of_norm_lt_one _ h).tsum_mul_left, ← _root_.pow_succ'] - -theorem geom_series_mul_one_add (x : R) (h : ‖x‖ < 1) : - (1 + x) * ∑' i : ℕ, x ^ i = 2 * ∑' i : ℕ, x ^ i - 1 := by - rw [add_mul, one_mul, geom_series_mul_shift x h, geom_series_succ x h, two_mul, add_sub_assoc] - -end NormedRingGeometric - /-! ### Summability tests based on comparison with geometric series -/ theorem summable_of_ratio_norm_eventually_le {α : Type*} [SeminormedAddCommGroup α] diff --git a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean index 9395e10f0cc6f..df6dd1f46c15f 100644 --- a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean +++ b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean @@ -397,7 +397,7 @@ theorem differentiableAt_Λ {s : ℂ} (hs : s ≠ 0 ∨ P.f₀ = 0) (hs' : s ≠ DifferentiableAt ℂ P.Λ s := by refine ((P.differentiable_Λ₀ s).sub ?_).sub ?_ · rcases hs with hs | hs - · simpa only [one_div] using (differentiableAt_inv' hs).smul_const P.f₀ + · simpa only [one_div] using (differentiableAt_inv hs).smul_const P.f₀ · simpa only [hs, smul_zero] using differentiableAt_const (0 : E) · rcases hs' with hs' | hs' · apply DifferentiableAt.smul_const diff --git a/Mathlib/Tactic/FunProp/Differentiable.lean b/Mathlib/Tactic/FunProp/Differentiable.lean index 5e20116dd53ac..1d81eec7d76f2 100644 --- a/Mathlib/Tactic/FunProp/Differentiable.lean +++ b/Mathlib/Tactic/FunProp/Differentiable.lean @@ -104,7 +104,6 @@ attribute [fun_prop] Differentiable.mul Differentiable.smul Differentiable.div - Differentiable.inv' Differentiable.inv DifferentiableAt.add @@ -113,7 +112,6 @@ attribute [fun_prop] DifferentiableAt.mul DifferentiableAt.smul DifferentiableAt.div - DifferentiableAt.inv' DifferentiableAt.inv DifferentiableOn.add @@ -122,7 +120,6 @@ attribute [fun_prop] DifferentiableOn.mul DifferentiableOn.smul DifferentiableOn.div - DifferentiableOn.inv' DifferentiableOn.inv From 643916d10f8fb87b1896a697001c1ea3c75252b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 24 Sep 2024 06:31:23 +0000 Subject: [PATCH 114/170] chore(SetTheory/Cardinal/Basic): organize file (#16359) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR moves related theorems together, and adds captions for each section. Superfluous `section`, `open`, `universe` and `variable` are deleted. We also move the proof of the well-ordering theorem from the `Ordinal/Basic` file to here, where it makes more sense and can be potentially used to prove other basic results. This has the nice effect of removing a bunch of imports to the file. No theorem statements were modified, aside from the very minor change of correcting `∀` to `Π` in `prod` and `mk_pi`. --- .../SimpleGraph/Regularity/Uniform.lean | 2 +- Mathlib/Data/DFinsupp/WellFounded.lean | 2 +- Mathlib/SetTheory/Cardinal/Basic.lean | 470 ++++++++++-------- Mathlib/SetTheory/Ordinal/Basic.lean | 36 -- .../Topology/EMetricSpace/Paracompact.lean | 2 +- Mathlib/Topology/PartitionOfUnity.lean | 1 - 6 files changed, 253 insertions(+), 260 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean index 005b689effd65..a6610b54a4ade 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.BigOperators.Ring import Mathlib.Combinatorics.SimpleGraph.Density import Mathlib.Data.Nat.Cast.Order.Field import Mathlib.Order.Partition.Equipartition -import Mathlib.SetTheory.Ordinal.Basic +import Mathlib.SetTheory.Cardinal.Basic /-! # Graph uniformity and uniform partitions diff --git a/Mathlib/Data/DFinsupp/WellFounded.lean b/Mathlib/Data/DFinsupp/WellFounded.lean index e10cffb7ca8e8..4262697dac419 100644 --- a/Mathlib/Data/DFinsupp/WellFounded.lean +++ b/Mathlib/Data/DFinsupp/WellFounded.lean @@ -6,8 +6,8 @@ Authors: Junyan Xu import Mathlib.Data.DFinsupp.Lex import Mathlib.Order.GameAdd import Mathlib.Order.Antisymmetrization -import Mathlib.SetTheory.Ordinal.Basic import Mathlib.Tactic.AdaptationNote +import Mathlib.SetTheory.Cardinal.Basic /-! # Well-foundedness of the lexicographic and product orders on `DFinsupp` and `Pi` diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index d2e7454569b96..d4ea99f073058 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -83,10 +83,12 @@ open Function Set Order noncomputable section -universe u v w +universe u v w v' w' variable {α β : Type u} +/-! ### Definition of cardinals -/ + /-- The equivalence relation on types given by equivalence (bijective correspondence) of types. Quotienting by this equivalence relation gives the cardinal numbers. -/ @@ -168,52 +170,6 @@ def map₂ (f : Type u → Type v → Type w) (hf : ∀ α β γ δ, α ≃ β Cardinal.{u} → Cardinal.{v} → Cardinal.{w} := Quotient.map₂ f fun α β ⟨e₁⟩ γ δ ⟨e₂⟩ => ⟨hf α β γ δ e₁ e₂⟩ -/-- The universe lift operation on cardinals. You can specify the universes explicitly with - `lift.{u v} : Cardinal.{v} → Cardinal.{max v u}` -/ -@[pp_with_univ] -def lift (c : Cardinal.{v}) : Cardinal.{max v u} := - map ULift.{u, v} (fun _ _ e => Equiv.ulift.trans <| e.trans Equiv.ulift.symm) c - -@[simp] -theorem mk_uLift (α) : #(ULift.{v, u} α) = lift.{v} #α := - rfl - --- Porting note: simpNF is not happy with universe levels, but this is needed as simp lemma --- further down in this file -/-- `lift.{max u v, u}` equals `lift.{v, u}`. -/ -@[simp, nolint simpNF] -theorem lift_umax : lift.{max u v, u} = lift.{v, u} := - funext fun a => inductionOn a fun _ => (Equiv.ulift.trans Equiv.ulift.symm).cardinal_eq - --- Porting note: simpNF is not happy with universe levels, but this is needed as simp lemma --- further down in this file -/-- `lift.{max v u, u}` equals `lift.{v, u}`. -/ -@[simp, nolint simpNF] -theorem lift_umax' : lift.{max v u, u} = lift.{v, u} := - lift_umax - --- Porting note: simpNF is not happy with universe levels, but this is needed as simp lemma --- further down in this file -/-- A cardinal lifted to a lower or equal universe equals itself. -/ -@[simp, nolint simpNF] -theorem lift_id' (a : Cardinal.{max u v}) : lift.{u} a = a := - inductionOn a fun _ => mk_congr Equiv.ulift - -/-- A cardinal lifted to the same universe equals itself. -/ -@[simp] -theorem lift_id (a : Cardinal) : lift.{u, u} a = a := - lift_id'.{u, u} a - -/-- A cardinal lifted to the zero universe equals itself. -/ --- porting note (#10618): simp can prove this --- @[simp] -theorem lift_uzero (a : Cardinal.{u}) : lift.{0} a = a := - lift_id'.{0, u} a - -@[simp] -theorem lift_lift.{u_1} (a : Cardinal.{u_1}) : lift.{w} (lift.{v} a) = lift.{max v w} a := - inductionOn a fun _ => (Equiv.ulift.trans <| Equiv.ulift.trans Equiv.ulift.symm).cardinal_eq - /-- We define the order on cardinal numbers by `#α ≤ #β` if and only if there exists an embedding (injective function) from α to β. -/ instance : LE Cardinal.{u} := @@ -262,6 +218,54 @@ theorem mk_subtype_le {α : Type u} (p : α → Prop) : #(Subtype p) ≤ #α := theorem mk_set_le (s : Set α) : #s ≤ #α := mk_subtype_le s +/-! ### Lifting cardinals to a higher universe -/ + +/-- The universe lift operation on cardinals. You can specify the universes explicitly with + `lift.{u v} : Cardinal.{v} → Cardinal.{max v u}` -/ +@[pp_with_univ] +def lift (c : Cardinal.{v}) : Cardinal.{max v u} := + map ULift.{u, v} (fun _ _ e => Equiv.ulift.trans <| e.trans Equiv.ulift.symm) c + +@[simp] +theorem mk_uLift (α) : #(ULift.{v, u} α) = lift.{v} #α := + rfl + +-- Porting note: simpNF is not happy with universe levels, but this is needed as simp lemma +-- further down in this file +/-- `lift.{max u v, u}` equals `lift.{v, u}`. -/ +@[simp, nolint simpNF] +theorem lift_umax : lift.{max u v, u} = lift.{v, u} := + funext fun a => inductionOn a fun _ => (Equiv.ulift.trans Equiv.ulift.symm).cardinal_eq + +-- Porting note: simpNF is not happy with universe levels, but this is needed as simp lemma +-- further down in this file +/-- `lift.{max v u, u}` equals `lift.{v, u}`. -/ +@[simp, nolint simpNF] +theorem lift_umax' : lift.{max v u, u} = lift.{v, u} := + lift_umax + +-- Porting note: simpNF is not happy with universe levels, but this is needed as simp lemma +-- further down in this file +/-- A cardinal lifted to a lower or equal universe equals itself. -/ +@[simp, nolint simpNF] +theorem lift_id' (a : Cardinal.{max u v}) : lift.{u} a = a := + inductionOn a fun _ => mk_congr Equiv.ulift + +/-- A cardinal lifted to the same universe equals itself. -/ +@[simp] +theorem lift_id (a : Cardinal) : lift.{u, u} a = a := + lift_id'.{u, u} a + +/-- A cardinal lifted to the zero universe equals itself. -/ +-- porting note (#10618): simp can prove this +-- @[simp] +theorem lift_uzero (a : Cardinal.{u}) : lift.{0} a = a := + lift_id'.{0, u} a + +@[simp] +theorem lift_lift.{u_1} (a : Cardinal.{u_1}) : lift.{w} (lift.{v} a) = lift.{max v w} a := + inductionOn a fun _ => (Equiv.ulift.trans <| Equiv.ulift.trans Equiv.ulift.symm).cardinal_eq + @[simp] lemma mk_preimage_down {s : Set α} : #(ULift.down.{v} ⁻¹' s) = lift.{v} (#s) := by rw [← mk_uLift, Cardinal.eq] @@ -307,6 +311,32 @@ theorem lift_le {a b : Cardinal.{v}} : lift.{u, v} a ≤ lift.{u, v} b ↔ a ≤ rw [← lift_umax] exact lift_mk_le.{u} +-- Porting note: simpNF is not happy with universe levels. +@[simp, nolint simpNF] +theorem lift_mk_shrink (α : Type u) [Small.{v} α] : + Cardinal.lift.{max u w} #(Shrink.{v} α) = Cardinal.lift.{max v w} #α := + lift_mk_eq.2 ⟨(equivShrink α).symm⟩ + +@[simp] +theorem lift_mk_shrink' (α : Type u) [Small.{v} α] : + Cardinal.lift.{u} #(Shrink.{v} α) = Cardinal.lift.{v} #α := + lift_mk_shrink.{u, v, 0} α + +@[simp] +theorem lift_mk_shrink'' (α : Type max u v) [Small.{v} α] : + Cardinal.lift.{u} #(Shrink.{v} α) = #α := by + rw [← lift_umax', lift_mk_shrink.{max u v, v, 0} α, ← lift_umax, lift_id] + +theorem lift_down {a : Cardinal.{u}} {b : Cardinal.{max u v}} : + b ≤ lift.{v,u} a → ∃ a', lift.{v,u} a' = b := + inductionOn₂ a b fun α β => by + rw [← lift_id #β, ← lift_umax, ← lift_umax.{u, v}, lift_mk_le.{v}] + exact fun ⟨f⟩ => + ⟨#(Set.range f), + Eq.symm <| lift_mk_eq.{_, _, v}.2 + ⟨Function.Embedding.equivOfSurjective (Embedding.codRestrict _ f Set.mem_range_self) + fun ⟨a, ⟨b, e⟩⟩ => ⟨b, Subtype.eq e⟩⟩⟩ + -- Porting note: changed `simps` to `simps!` because the linter told to do so. /-- `Cardinal.lift` as an `OrderEmbedding`. -/ @[simps! (config := .asFn)] @@ -329,6 +359,36 @@ theorem lift_strictMono : StrictMono lift := fun _ _ => lift_lt.2 theorem lift_monotone : Monotone lift := lift_strictMono.monotone +@[simp] +theorem lift_min {a b : Cardinal} : lift.{u, v} (min a b) = min (lift.{u, v} a) (lift.{u, v} b) := + lift_monotone.map_min + +@[simp] +theorem lift_max {a b : Cardinal} : lift.{u, v} (max a b) = max (lift.{u, v} a) (lift.{u, v} b) := + lift_monotone.map_max + +-- Porting note: simpNF is not happy with universe levels. +@[simp, nolint simpNF] +theorem lift_umax_eq {a : Cardinal.{u}} {b : Cardinal.{v}} : + lift.{max v w} a = lift.{max u w} b ↔ lift.{v} a = lift.{u} b := by + rw [← lift_lift.{v, w, u}, ← lift_lift.{u, w, v}, lift_inj] + +theorem le_lift_iff {a : Cardinal.{u}} {b : Cardinal.{max u v}} : + b ≤ lift.{v, u} a ↔ ∃ a', lift.{v, u} a' = b ∧ a' ≤ a := + ⟨fun h => + let ⟨a', e⟩ := lift_down h + ⟨a', e, lift_le.1 <| e.symm ▸ h⟩, + fun ⟨_, e, h⟩ => e ▸ lift_le.2 h⟩ + +theorem lt_lift_iff {a : Cardinal.{u}} {b : Cardinal.{max u v}} : + b < lift.{v, u} a ↔ ∃ a', lift.{v, u} a' = b ∧ a' < a := + ⟨fun h => + let ⟨a', e⟩ := lift_down h.le + ⟨a', e, lift_lt.1 <| e.symm ▸ h⟩, + fun ⟨_, e, h⟩ => e ▸ lift_lt.2 h⟩ + +/-! ### Basic cardinals -/ + instance : Zero Cardinal.{u} := -- `PEmpty` might be more canonical, but this is convenient for defeq with natCast ⟨lift #(Fin 0)⟩ @@ -538,9 +598,7 @@ theorem mk_powerset {α : Type u} (s : Set α) : #(↥(𝒫 s)) = 2 ^ #(↥s) := theorem lift_two_power (a : Cardinal) : lift.{v} (2 ^ a) = 2 ^ lift.{v} a := by simp [← one_add_one_eq_two] -section OrderProperties - -open Sum +/-! ### Order properties -/ protected theorem zero_le : ∀ a : Cardinal, 0 ≤ a := by rintro ⟨α⟩ @@ -639,8 +697,6 @@ theorem power_le_power_right {a b c : Cardinal} : a ≤ b → a ^ c ≤ b ^ c := theorem power_pos {a : Cardinal} (b : Cardinal) (ha : 0 < a) : 0 < a ^ b := (power_ne_zero _ ha.ne').bot_lt -end OrderProperties - protected theorem lt_wf : @WellFounded Cardinal.{u} (· < ·) := ⟨fun a => by_contradiction fun h => by @@ -682,6 +738,22 @@ lemma iInf_eq_zero_iff {ι : Sort*} {f : ι → Cardinal} : (⨅ i, f i) = 0 ↔ IsEmpty ι ∨ ∃ i, f i = 0 := by simp [iInf, sInf_eq_zero_iff] +/-- A variant of `ciSup_of_empty` but with `0` on the RHS for convenience -/ +protected theorem iSup_of_empty {ι} (f : ι → Cardinal) [IsEmpty ι] : iSup f = 0 := + ciSup_of_empty f + +@[simp] +theorem lift_sInf (s : Set Cardinal) : lift.{u, v} (sInf s) = sInf (lift.{u, v} '' s) := by + rcases eq_empty_or_nonempty s with (rfl | hs) + · simp + · exact lift_monotone.map_csInf hs + +@[simp] +theorem lift_iInf {ι} (f : ι → Cardinal) : lift.{u, v} (iInf f) = ⨅ i, lift.{u, v} (f i) := by + unfold iInf + convert lift_sInf (range f) + simp_rw [← comp_apply (f := lift), range_comp] + /-- Note that the successor of `c` is not the same as `c + 1` except in the case of finite `c`. -/ instance : SuccOrder Cardinal := ConditionallyCompleteLinearOrder.toSuccOrder @@ -708,6 +780,15 @@ theorem add_one_le_succ (c : Cardinal.{u}) : c + 1 ≤ succ c := by #γ + 1 = #(Option γ) := mk_option.symm _ ≤ #β := (f.optionElim b hb).cardinal_le +@[simp] +theorem lift_succ (a) : lift.{v, u} (succ a) = succ (lift.{v, u} a) := + le_antisymm + (le_of_not_gt fun h => by + rcases lt_lift_iff.1 h with ⟨b, e, h⟩ + rw [lt_succ_iff, ← lift_le, e] at h + exact h.not_lt (lt_succ _)) + (succ_le_of_lt <| lift_lt.2 <| lt_succ a) + /-- A cardinal is a limit if it is not zero or a successor cardinal. Note that `ℵ₀` is a limit cardinal by this definition, but `0` isn't. Deprecated. Use `Order.IsSuccLimit` instead. -/ @@ -748,15 +829,20 @@ alias isSuccLimit_zero := isSuccPrelimit_zero end deprecated +/-! ### Indexed cardinal `sum` -/ + /-- The indexed sum of cardinals is the cardinality of the indexed disjoint union, i.e. sigma type. -/ def sum {ι} (f : ι → Cardinal) : Cardinal := - mk (Σi, (f i).out) + mk (Σ i, (f i).out) theorem le_sum {ι} (f : ι → Cardinal) (i) : f i ≤ sum f := by rw [← Quotient.out_eq (f i)] exact ⟨⟨fun a => ⟨i, a⟩, fun a b h => by injection h⟩⟩ +theorem iSup_le_sum {ι} (f : ι → Cardinal) : iSup f ≤ sum f := + ciSup_le' <| le_sum _ + @[simp] theorem mk_sigma {ι} (f : ι → Type*) : #(Σ i, f i) = sum fun i => #(f i) := mk_congr <| Equiv.sigmaCongrRight fun _ => outMkEquiv.symm @@ -822,6 +908,42 @@ theorem lift_mk_le_lift_mk_mul_of_lift_mk_preimage_le {α : Type u} {β : Type v Equiv.ulift.symm)).trans_le (hf b) +theorem sum_nat_eq_add_sum_succ (f : ℕ → Cardinal.{u}) : + Cardinal.sum f = f 0 + Cardinal.sum fun i => f (i + 1) := by + refine (Equiv.sigmaNatSucc fun i => Quotient.out (f i)).cardinal_eq.trans ?_ + simp only [mk_sum, mk_out, lift_id, mk_sigma] + +end Cardinal + +/-! ### Well-ordering theorem -/ + +open Cardinal in +theorem nonempty_embedding_to_cardinal : Nonempty (α ↪ Cardinal.{u}) := + (Embedding.total _ _).resolve_left fun ⟨⟨f, hf⟩⟩ => + let g : α → Cardinal.{u} := invFun f + let ⟨x, (hx : g x = 2 ^ sum g)⟩ := invFun_surjective hf (2 ^ sum g) + have : g x ≤ sum g := le_sum.{u, u} g x + not_le_of_gt (by rw [hx]; exact cantor _) this + +/-- An embedding of any type to the set of cardinals in its universe. -/ +def embeddingToCardinal : α ↪ Cardinal.{u} := + Classical.choice nonempty_embedding_to_cardinal + +/-- Any type can be endowed with a well order, obtained by pulling back the well order over +cardinals by some embedding. -/ +def WellOrderingRel : α → α → Prop := + embeddingToCardinal ⁻¹'o (· < ·) + +instance WellOrderingRel.isWellOrder : IsWellOrder α WellOrderingRel := + (RelEmbedding.preimage _ _).isWellOrder + +instance IsWellOrder.subtype_nonempty : Nonempty { r // IsWellOrder α r } := + ⟨⟨WellOrderingRel, inferInstance⟩⟩ + +/-! ### Small sets of cardinals -/ + +namespace Cardinal + /-- The range of an indexed cardinal function, whose outputs live in a higher universe than the inputs, is always bounded above. -/ theorem bddAbove_range {ι : Type u} (f : ι → Cardinal.{max u v}) : BddAbove (Set.range f) := @@ -864,8 +986,7 @@ theorem bddAbove_range_comp {ι : Type u} {f : ι → Cardinal.{v}} (hf : BddAbo rw [range_comp] exact bddAbove_image g hf -theorem iSup_le_sum {ι} (f : ι → Cardinal) : iSup f ≤ sum f := - ciSup_le' <| le_sum _ +/-! ### Bounds on suprema -/ theorem sum_le_iSup_lift {ι : Type u} (f : ι → Cardinal.{max u v}) : sum f ≤ Cardinal.lift #ι * iSup f := by @@ -876,16 +997,54 @@ theorem sum_le_iSup {ι : Type u} (f : ι → Cardinal.{u}) : sum f ≤ #ι * iS rw [← lift_id #ι] exact sum_le_iSup_lift f -theorem sum_nat_eq_add_sum_succ (f : ℕ → Cardinal.{u}) : - Cardinal.sum f = f 0 + Cardinal.sum fun i => f (i + 1) := by - refine (Equiv.sigmaNatSucc fun i => Quotient.out (f i)).cardinal_eq.trans ?_ - simp only [mk_sum, mk_out, lift_id, mk_sigma] +/-- The lift of a supremum is the supremum of the lifts. -/ +theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) : + lift.{u} (sSup s) = sSup (lift.{u} '' s) := by + apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _) + · intro c hc + by_contra h + obtain ⟨d, rfl⟩ := Cardinal.lift_down (not_le.1 h).le + simp_rw [lift_le] at h hc + rw [csSup_le_iff' hs] at h + exact h fun a ha => lift_le.1 <| hc (mem_image_of_mem _ ha) + · rintro i ⟨j, hj, rfl⟩ + exact lift_le.2 (le_csSup hs hj) --- Porting note: LFS is not in normal form. --- @[simp] -/-- A variant of `ciSup_of_empty` but with `0` on the RHS for convenience -/ -protected theorem iSup_of_empty {ι} (f : ι → Cardinal) [IsEmpty ι] : iSup f = 0 := - ciSup_of_empty f +/-- The lift of a supremum is the supremum of the lifts. -/ +theorem lift_iSup {ι : Type v} {f : ι → Cardinal.{w}} (hf : BddAbove (range f)) : + lift.{u} (iSup f) = ⨆ i, lift.{u} (f i) := by + rw [iSup, iSup, lift_sSup hf, ← range_comp] + simp [Function.comp_def] + +/-- To prove that the lift of a supremum is bounded by some cardinal `t`, +it suffices to show that the lift of each cardinal is bounded by `t`. -/ +theorem lift_iSup_le {ι : Type v} {f : ι → Cardinal.{w}} {t : Cardinal} (hf : BddAbove (range f)) + (w : ∀ i, lift.{u} (f i) ≤ t) : lift.{u} (iSup f) ≤ t := by + rw [lift_iSup hf] + exact ciSup_le' w + +@[simp] +theorem lift_iSup_le_iff {ι : Type v} {f : ι → Cardinal.{w}} (hf : BddAbove (range f)) + {t : Cardinal} : lift.{u} (iSup f) ≤ t ↔ ∀ i, lift.{u} (f i) ≤ t := by + rw [lift_iSup hf] + exact ciSup_le_iff' (bddAbove_range_comp.{_,_,u} hf _) + +/-- To prove an inequality between the lifts to a common universe of two different supremums, +it suffices to show that the lift of each cardinal from the smaller supremum +if bounded by the lift of some cardinal from the larger supremum. +-/ +theorem lift_iSup_le_lift_iSup {ι : Type v} {ι' : Type v'} {f : ι → Cardinal.{w}} + {f' : ι' → Cardinal.{w'}} (hf : BddAbove (range f)) (hf' : BddAbove (range f')) {g : ι → ι'} + (h : ∀ i, lift.{w'} (f i) ≤ lift.{w} (f' (g i))) : lift.{w'} (iSup f) ≤ lift.{w} (iSup f') := by + rw [lift_iSup hf, lift_iSup hf'] + exact ciSup_mono' (bddAbove_range_comp.{_,_,w} hf' _) fun i => ⟨_, h i⟩ + +/-- A variant of `lift_iSup_le_lift_iSup` with universes specialized via `w = v` and `w' = v'`. +This is sometimes necessary to avoid universe unification issues. -/ +theorem lift_iSup_le_lift_iSup' {ι : Type v} {ι' : Type v'} {f : ι → Cardinal.{v}} + {f' : ι' → Cardinal.{v'}} (hf : BddAbove (range f)) (hf' : BddAbove (range f')) (g : ι → ι') + (h : ∀ i, lift.{v'} (f i) ≤ lift.{v} (f' (g i))) : lift.{v'} (iSup f) ≤ lift.{v} (iSup f') := + lift_iSup_le_lift_iSup hf hf' h lemma exists_eq_of_iSup_eq_of_not_isSuccPrelimit {ι : Type u} (f : ι → Cardinal.{v}) (ω : Cardinal.{v}) @@ -920,29 +1079,15 @@ lemma exists_eq_of_iSup_eq_of_not_isLimit rw [← le_zero_iff] at h ⊢ exact (le_ciSup hf _).trans h --- Porting note: simpNF is not happy with universe levels. -@[simp, nolint simpNF] -theorem lift_mk_shrink (α : Type u) [Small.{v} α] : - Cardinal.lift.{max u w} #(Shrink.{v} α) = Cardinal.lift.{max v w} #α := - lift_mk_eq.2 ⟨(equivShrink α).symm⟩ - -@[simp] -theorem lift_mk_shrink' (α : Type u) [Small.{v} α] : - Cardinal.lift.{u} #(Shrink.{v} α) = Cardinal.lift.{v} #α := - lift_mk_shrink.{u, v, 0} α - -@[simp] -theorem lift_mk_shrink'' (α : Type max u v) [Small.{v} α] : - Cardinal.lift.{u} #(Shrink.{v} α) = #α := by - rw [← lift_umax', lift_mk_shrink.{max u v, v, 0} α, ← lift_umax, lift_id] +/-! ### Indexed cardinal `prod` -/ /-- The indexed product of cardinals is the cardinality of the Pi type (dependent product). -/ def prod {ι : Type u} (f : ι → Cardinal) : Cardinal := - #(∀ i, (f i).out) + #(Π i, (f i).out) @[simp] -theorem mk_pi {ι : Type u} (α : ι → Type v) : #(∀ i, α i) = prod fun i => #(α i) := +theorem mk_pi {ι : Type u} (α : ι → Type v) : #(Π i, α i) = prod fun i => #(α i) := mk_congr <| Equiv.piCongrRight fun _ => outMkEquiv.symm @[simp] @@ -998,115 +1143,26 @@ theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{ Cardinal.prod, lift_prod, Fintype.prod_option, lift_mul, ← h fun a => f (some a)] simp only [lift_id] -@[simp] -theorem lift_sInf (s : Set Cardinal) : lift.{u, v} (sInf s) = sInf (lift.{u, v} '' s) := by - rcases eq_empty_or_nonempty s with (rfl | hs) - · simp - · exact lift_monotone.map_csInf hs - -@[simp] -theorem lift_iInf {ι} (f : ι → Cardinal) : lift.{u, v} (iInf f) = ⨅ i, lift.{u, v} (f i) := by - unfold iInf - convert lift_sInf (range f) - simp_rw [← comp_apply (f := lift), range_comp] - -theorem lift_down {a : Cardinal.{u}} {b : Cardinal.{max u v}} : - b ≤ lift.{v,u} a → ∃ a', lift.{v,u} a' = b := - inductionOn₂ a b fun α β => by - rw [← lift_id #β, ← lift_umax, ← lift_umax.{u, v}, lift_mk_le.{v}] - exact fun ⟨f⟩ => - ⟨#(Set.range f), - Eq.symm <| lift_mk_eq.{_, _, v}.2 - ⟨Function.Embedding.equivOfSurjective (Embedding.codRestrict _ f Set.mem_range_self) - fun ⟨a, ⟨b, e⟩⟩ => ⟨b, Subtype.eq e⟩⟩⟩ - -theorem le_lift_iff {a : Cardinal.{u}} {b : Cardinal.{max u v}} : - b ≤ lift.{v, u} a ↔ ∃ a', lift.{v, u} a' = b ∧ a' ≤ a := - ⟨fun h => - let ⟨a', e⟩ := lift_down h - ⟨a', e, lift_le.1 <| e.symm ▸ h⟩, - fun ⟨_, e, h⟩ => e ▸ lift_le.2 h⟩ - -theorem lt_lift_iff {a : Cardinal.{u}} {b : Cardinal.{max u v}} : - b < lift.{v, u} a ↔ ∃ a', lift.{v, u} a' = b ∧ a' < a := - ⟨fun h => - let ⟨a', e⟩ := lift_down h.le - ⟨a', e, lift_lt.1 <| e.symm ▸ h⟩, - fun ⟨_, e, h⟩ => e ▸ lift_lt.2 h⟩ - -@[simp] -theorem lift_succ (a) : lift.{v, u} (succ a) = succ (lift.{v, u} a) := - le_antisymm - (le_of_not_gt fun h => by - rcases lt_lift_iff.1 h with ⟨b, e, h⟩ - rw [lt_succ_iff, ← lift_le, e] at h - exact h.not_lt (lt_succ _)) - (succ_le_of_lt <| lift_lt.2 <| lt_succ a) - --- Porting note: simpNF is not happy with universe levels. -@[simp, nolint simpNF] -theorem lift_umax_eq {a : Cardinal.{u}} {b : Cardinal.{v}} : - lift.{max v w} a = lift.{max u w} b ↔ lift.{v} a = lift.{u} b := by - rw [← lift_lift.{v, w, u}, ← lift_lift.{u, w, v}, lift_inj] - -@[simp] -theorem lift_min {a b : Cardinal} : lift.{u, v} (min a b) = min (lift.{u, v} a) (lift.{u, v} b) := - lift_monotone.map_min - -@[simp] -theorem lift_max {a b : Cardinal} : lift.{u, v} (max a b) = max (lift.{u, v} a) (lift.{u, v} b) := - lift_monotone.map_max - -/-- The lift of a supremum is the supremum of the lifts. -/ -theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) : - lift.{u} (sSup s) = sSup (lift.{u} '' s) := by - apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _) - · intro c hc - by_contra h - obtain ⟨d, rfl⟩ := Cardinal.lift_down (not_le.1 h).le - simp_rw [lift_le] at h hc - rw [csSup_le_iff' hs] at h - exact h fun a ha => lift_le.1 <| hc (mem_image_of_mem _ ha) - · rintro i ⟨j, hj, rfl⟩ - exact lift_le.2 (le_csSup hs hj) - -/-- The lift of a supremum is the supremum of the lifts. -/ -theorem lift_iSup {ι : Type v} {f : ι → Cardinal.{w}} (hf : BddAbove (range f)) : - lift.{u} (iSup f) = ⨆ i, lift.{u} (f i) := by - rw [iSup, iSup, lift_sSup hf, ← range_comp] - simp [Function.comp_def] - -/-- To prove that the lift of a supremum is bounded by some cardinal `t`, -it suffices to show that the lift of each cardinal is bounded by `t`. -/ -theorem lift_iSup_le {ι : Type v} {f : ι → Cardinal.{w}} {t : Cardinal} (hf : BddAbove (range f)) - (w : ∀ i, lift.{u} (f i) ≤ t) : lift.{u} (iSup f) ≤ t := by - rw [lift_iSup hf] - exact ciSup_le' w - -@[simp] -theorem lift_iSup_le_iff {ι : Type v} {f : ι → Cardinal.{w}} (hf : BddAbove (range f)) - {t : Cardinal} : lift.{u} (iSup f) ≤ t ↔ ∀ i, lift.{u} (f i) ≤ t := by - rw [lift_iSup hf] - exact ciSup_le_iff' (bddAbove_range_comp.{_,_,u} hf _) - -universe v' w' - -/-- To prove an inequality between the lifts to a common universe of two different supremums, -it suffices to show that the lift of each cardinal from the smaller supremum -if bounded by the lift of some cardinal from the larger supremum. --/ -theorem lift_iSup_le_lift_iSup {ι : Type v} {ι' : Type v'} {f : ι → Cardinal.{w}} - {f' : ι' → Cardinal.{w'}} (hf : BddAbove (range f)) (hf' : BddAbove (range f')) {g : ι → ι'} - (h : ∀ i, lift.{w'} (f i) ≤ lift.{w} (f' (g i))) : lift.{w'} (iSup f) ≤ lift.{w} (iSup f') := by - rw [lift_iSup hf, lift_iSup hf'] - exact ciSup_mono' (bddAbove_range_comp.{_,_,w} hf' _) fun i => ⟨_, h i⟩ +/-- **König's theorem** -/ +theorem sum_lt_prod {ι} (f g : ι → Cardinal) (H : ∀ i, f i < g i) : sum f < prod g := + lt_of_not_ge fun ⟨F⟩ => by + have : Inhabited (∀ i : ι, (g i).out) := by + refine ⟨fun i => Classical.choice <| mk_ne_zero_iff.1 ?_⟩ + rw [mk_out] + exact (H i).ne_bot + let G := invFun F + have sG : Surjective G := invFun_surjective F.2 + choose C hc using + show ∀ i, ∃ b, ∀ a, G ⟨i, a⟩ i ≠ b by + intro i + simp only [not_exists.symm, not_forall.symm] + refine fun h => (H i).not_le ?_ + rw [← mk_out (f i), ← mk_out (g i)] + exact ⟨Embedding.ofSurjective _ h⟩ + let ⟨⟨i, a⟩, h⟩ := sG C + exact hc i a (congr_fun h _) -/-- A variant of `lift_iSup_le_lift_iSup` with universes specialized via `w = v` and `w' = v'`. -This is sometimes necessary to avoid universe unification issues. -/ -theorem lift_iSup_le_lift_iSup' {ι : Type v} {ι' : Type v'} {f : ι → Cardinal.{v}} - {f' : ι' → Cardinal.{v'}} (hf : BddAbove (range f)) (hf' : BddAbove (range f')) (g : ι → ι') - (h : ∀ i, lift.{v'} (f i) ≤ lift.{v} (f' (g i))) : lift.{v'} (iSup f) ≤ lift.{v} (iSup f') := - lift_iSup_le_lift_iSup hf hf' h +/-! ### The first infinite cardinal `aleph0` -/ /-- `ℵ₀` is the smallest infinite cardinal. -/ def aleph0 : Cardinal.{u} := @@ -1145,7 +1201,6 @@ theorem lift_lt_aleph0 {c : Cardinal.{u}} : lift.{v} c < ℵ₀ ↔ c < ℵ₀ : rw [← lift_aleph0.{v, u}, lift_lt] /-! ### Properties about the cast from `ℕ` -/ -section castFromN -- porting note (#10618): simp can prove this -- @[simp] @@ -1340,6 +1395,8 @@ theorem one_le_iff_ne_zero {c : Cardinal} : 1 ≤ c ↔ c ≠ 0 := by theorem lt_one_iff_zero {c : Cardinal} : c < 1 ↔ c = 0 := by simpa using lt_succ_bot_iff (a := c) +/-! ### Properties about `aleph0` -/ + theorem nat_lt_aleph0 (n : ℕ) : (n : Cardinal.{u}) < ℵ₀ := succ_le_iff.1 (by @@ -1625,31 +1682,7 @@ theorem mk_int : #ℤ = ℵ₀ := theorem mk_pNat : #ℕ+ = ℵ₀ := mk_denumerable ℕ+ -end castFromN - -variable {c : Cardinal} - -/-- **König's theorem** -/ -theorem sum_lt_prod {ι} (f g : ι → Cardinal) (H : ∀ i, f i < g i) : sum f < prod g := - lt_of_not_ge fun ⟨F⟩ => by - have : Inhabited (∀ i : ι, (g i).out) := by - refine ⟨fun i => Classical.choice <| mk_ne_zero_iff.1 ?_⟩ - rw [mk_out] - exact (H i).ne_bot - let G := invFun F - have sG : Surjective G := invFun_surjective F.2 - choose C hc using - show ∀ i, ∃ b, ∀ a, G ⟨i, a⟩ i ≠ b by - intro i - simp only [not_exists.symm, not_forall.symm] - refine fun h => (H i).not_le ?_ - rw [← mk_out (f i), ← mk_out (g i)] - exact ⟨Embedding.ofSurjective _ h⟩ - let ⟨⟨i, a⟩, h⟩ := sG C - exact hc i a (congr_fun h _) - -/-! Cardinalities of sets: cardinality of empty, finite sets, unions, subsets etc. -/ -section sets +/-! ### Cardinalities of basic sets and types -/ -- porting note (#10618): simp can prove this -- @[simp] @@ -1997,9 +2030,7 @@ theorem three_le {α : Type*} (h : 3 ≤ #α) (x : α) (y : α) : ∃ z : α, z have := exists_not_mem_of_length_lt [x, y] this simpa [not_or] using this -end sets - -section powerlt +/-! ### `powerlt` operation -/ /-- The function `a ^< b`, defined as the supremum of `a ^ c` for `c < b`. -/ def powerlt (a b : Cardinal.{u}) : Cardinal.{u} := @@ -2044,7 +2075,6 @@ theorem powerlt_zero {a : Cardinal} : a ^< 0 = 0 := by convert Cardinal.iSup_of_empty _ exact Subtype.isEmpty_of_false fun x => mem_Iio.not.mpr (Cardinal.zero_le x).not_lt -end powerlt end Cardinal -- namespace Tactic @@ -2067,4 +2097,4 @@ end Cardinal -- end Tactic -set_option linter.style.longFile 2100 +set_option linter.style.longFile 2200 diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 4fe487ab74e97..0c445ec3d40bb 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -67,42 +67,6 @@ universe u v w variable {α : Type u} {β : Type*} {γ : Type*} {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} -/-! ### Well order on an arbitrary type -/ - - -section WellOrderingThm - --- Porting note: `parameter` does not work --- parameter {σ : Type u} -variable {σ : Type u} - - -open Function - -theorem nonempty_embedding_to_cardinal : Nonempty (σ ↪ Cardinal.{u}) := - (Embedding.total _ _).resolve_left fun ⟨⟨f, hf⟩⟩ => - let g : σ → Cardinal.{u} := invFun f - let ⟨x, (hx : g x = 2 ^ sum g)⟩ := invFun_surjective hf (2 ^ sum g) - have : g x ≤ sum g := le_sum.{u, u} g x - not_le_of_gt (by rw [hx]; exact cantor _) this - -/-- An embedding of any type to the set of cardinals. -/ -def embeddingToCardinal : σ ↪ Cardinal.{u} := - Classical.choice nonempty_embedding_to_cardinal - -/-- Any type can be endowed with a well order, obtained by pulling back the well order over -cardinals by some embedding. -/ -def WellOrderingRel : σ → σ → Prop := - embeddingToCardinal ⁻¹'o (· < ·) - -instance WellOrderingRel.isWellOrder : IsWellOrder σ WellOrderingRel := - (RelEmbedding.preimage _ _).isWellOrder - -instance IsWellOrder.subtype_nonempty : Nonempty { r // IsWellOrder σ r } := - ⟨⟨WellOrderingRel, inferInstance⟩⟩ - -end WellOrderingThm - /-! ### Definition of ordinals -/ diff --git a/Mathlib/Topology/EMetricSpace/Paracompact.lean b/Mathlib/Topology/EMetricSpace/Paracompact.lean index dc2427907aac4..f7e7082bc036a 100644 --- a/Mathlib/Topology/EMetricSpace/Paracompact.lean +++ b/Mathlib/Topology/EMetricSpace/Paracompact.lean @@ -3,10 +3,10 @@ Copyright (c) 2021 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.SetTheory.Ordinal.Basic import Mathlib.Tactic.GCongr import Mathlib.Topology.Compactness.Paracompact import Mathlib.Topology.EMetricSpace.Basic +import Mathlib.SetTheory.Cardinal.Basic /-! # (Extended) metric spaces are paracompact diff --git a/Mathlib/Topology/PartitionOfUnity.lean b/Mathlib/Topology/PartitionOfUnity.lean index a98ad48c12803..bdc558694b1cd 100644 --- a/Mathlib/Topology/PartitionOfUnity.lean +++ b/Mathlib/Topology/PartitionOfUnity.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.Finprod -import Mathlib.SetTheory.Ordinal.Basic import Mathlib.Topology.ContinuousFunction.Algebra import Mathlib.Topology.Compactness.Paracompact import Mathlib.Topology.ShrinkingLemma From 50ab2964644f6a8b5aeee08b3aa974099a56fa25 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 24 Sep 2024 06:31:24 +0000 Subject: [PATCH 115/170] chore(AlexandrovDiscrete): move `exterior` to new files (#16957) I'm going to use `exterior` in files that don't need to know about `AlexandrovDiscrete`. --- Mathlib.lean | 2 + Mathlib/Topology/AlexandrovDiscrete.lean | 102 +-------------------- Mathlib/Topology/Compactness/Exterior.lean | 30 ++++++ Mathlib/Topology/Defs/Filter.lean | 13 +++ Mathlib/Topology/Exterior.lean | 98 ++++++++++++++++++++ 5 files changed, 145 insertions(+), 100 deletions(-) create mode 100644 Mathlib/Topology/Compactness/Exterior.lean create mode 100644 Mathlib/Topology/Exterior.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9a201b9b4f9a4..4de0c7bf38993 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4542,6 +4542,7 @@ import Mathlib.Topology.CompactOpen import Mathlib.Topology.Compactification.OnePoint import Mathlib.Topology.Compactness.Compact import Mathlib.Topology.Compactness.CompactlyGeneratedSpace +import Mathlib.Topology.Compactness.Exterior import Mathlib.Topology.Compactness.Lindelof import Mathlib.Topology.Compactness.LocallyCompact import Mathlib.Topology.Compactness.Paracompact @@ -4592,6 +4593,7 @@ import Mathlib.Topology.EMetricSpace.Lipschitz import Mathlib.Topology.EMetricSpace.Paracompact import Mathlib.Topology.EMetricSpace.Pi import Mathlib.Topology.ExtendFrom +import Mathlib.Topology.Exterior import Mathlib.Topology.ExtremallyDisconnected import Mathlib.Topology.FiberBundle.Basic import Mathlib.Topology.FiberBundle.Constructions diff --git a/Mathlib/Topology/AlexandrovDiscrete.lean b/Mathlib/Topology/AlexandrovDiscrete.lean index 2c3353a35125b..b03c9b2cb45eb 100644 --- a/Mathlib/Topology/AlexandrovDiscrete.lean +++ b/Mathlib/Topology/AlexandrovDiscrete.lean @@ -5,9 +5,8 @@ Authors: Yaël Dillies -/ import Mathlib.Data.Set.Image import Mathlib.Topology.Bases -import Mathlib.Tactic.Peel import Mathlib.Topology.Inseparable -import Mathlib.Topology.Compactness.Compact +import Mathlib.Topology.Compactness.Exterior /-! # Alexandrov-discrete topological spaces @@ -21,8 +20,6 @@ minimal neighborhood, which we call the *exterior* of the set. ## Main declarations * `AlexandrovDiscrete`: Prop-valued typeclass for a topological space to be Alexandrov-discrete -* `exterior`: Intersection of all neighborhoods of a set. When the space is Alexandrov-discrete, - this is the minimal neighborhood of the set. ## Notes @@ -119,89 +116,6 @@ end AlexandrovDiscrete variable {s t : Set α} {a x y : α} -/-- The *exterior* of a set is the intersection of all its neighborhoods. In an Alexandrov-discrete -space, this is the smallest neighborhood of the set. - -Note that this construction is unnamed in the literature. We choose the name in analogy to -`interior`. -/ -def exterior (s : Set α) : Set α := (𝓝ˢ s).ker - -lemma exterior_singleton_eq_ker_nhds (a : α) : exterior {a} = (𝓝 a).ker := by simp [exterior] - -@[simp] -theorem mem_exterior_singleton : x ∈ exterior {y} ↔ x ⤳ y := by - rw [exterior_singleton_eq_ker_nhds, ker_nhds_eq_specializes, mem_setOf] - -lemma exterior_def (s : Set α) : exterior s = ⋂₀ {t : Set α | IsOpen t ∧ s ⊆ t} := - (hasBasis_nhdsSet _).ker.trans sInter_eq_biInter.symm - -lemma mem_exterior : a ∈ exterior s ↔ ∀ U, IsOpen U → s ⊆ U → a ∈ U := by simp [exterior_def] - -lemma subset_exterior_iff : s ⊆ exterior t ↔ ∀ U, IsOpen U → t ⊆ U → s ⊆ U := by - simp [exterior_def] - -lemma subset_exterior : s ⊆ exterior s := subset_exterior_iff.2 fun _ _ ↦ id - -lemma exterior_minimal (h₁ : s ⊆ t) (h₂ : IsOpen t) : exterior s ⊆ t := by - rw [exterior_def]; exact sInter_subset_of_mem ⟨h₂, h₁⟩ - -lemma IsOpen.exterior_eq (h : IsOpen s) : exterior s = s := - (exterior_minimal Subset.rfl h).antisymm subset_exterior - -lemma IsOpen.exterior_subset (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t := - ⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩ - -@[deprecated (since := "2024-09-18")] alias IsOpen.exterior_subset_iff := IsOpen.exterior_subset - -@[simp] -theorem exterior_iUnion {ι : Sort*} (s : ι → Set α) : - exterior (⋃ i, s i) = ⋃ i, exterior (s i) := by - simp only [exterior, nhdsSet_iUnion, ker_iSup] - -@[simp] -theorem exterior_union (s t : Set α) : exterior (s ∪ t) = exterior s ∪ exterior t := by - simp only [exterior, nhdsSet_union, ker_sup] - -@[simp] -theorem exterior_sUnion (S : Set (Set α)) : exterior (⋃₀ S) = ⋃ s ∈ S, exterior s := by - simp only [sUnion_eq_biUnion, exterior_iUnion] - -theorem mem_exterior_iff_specializes : a ∈ exterior s ↔ ∃ b ∈ s, a ⤳ b := calc - a ∈ exterior s ↔ a ∈ exterior (⋃ x ∈ s, {x}) := by simp - _ ↔ ∃ b ∈ s, a ⤳ b := by - simp only [exterior_iUnion, mem_exterior_singleton, mem_iUnion₂, exists_prop] - -@[mono] lemma exterior_mono : Monotone (exterior : Set α → Set α) := - fun _s _t h ↦ ker_mono <| nhdsSet_mono h - -/-- This name was used to be used for the `Iff` version, -see `exterior_subset_exterior_iff_nhdsSet`. --/ -@[gcongr] lemma exterior_subset_exterior (h : s ⊆ t) : exterior s ⊆ exterior t := exterior_mono h - -@[simp] lemma exterior_subset_exterior_iff_nhdsSet : exterior s ⊆ exterior t ↔ 𝓝ˢ s ≤ 𝓝ˢ t := by - simp (config := {contextual := true}) only [subset_exterior_iff, (hasBasis_nhdsSet _).ge_iff, - and_imp, IsOpen.mem_nhdsSet, IsOpen.exterior_subset] - -theorem exterior_eq_exterior_iff_nhdsSet : exterior s = exterior t ↔ 𝓝ˢ s = 𝓝ˢ t := by - simp [le_antisymm_iff] - -lemma specializes_iff_exterior_subset : x ⤳ y ↔ exterior {x} ⊆ exterior {y} := by - simp [Specializes] - -@[simp] lemma exterior_empty : exterior (∅ : Set α) = ∅ := isOpen_empty.exterior_eq -@[simp] lemma exterior_univ : exterior (univ : Set α) = univ := isOpen_univ.exterior_eq - -@[simp] lemma exterior_eq_empty : exterior s = ∅ ↔ s = ∅ := - ⟨eq_bot_mono subset_exterior, by rintro rfl; exact exterior_empty⟩ - -@[simp] lemma nhdsSet_exterior (s : Set α) : 𝓝ˢ (exterior s) = 𝓝ˢ s := by - refine le_antisymm ((hasBasis_nhdsSet _).ge_iff.2 ?_) (nhdsSet_mono subset_exterior) - exact fun U ⟨hUo, hsU⟩ ↦ hUo.mem_nhdsSet.2 <| hUo.exterior_subset.2 hsU - -@[simp] lemma exterior_exterior (s : Set α) : exterior (exterior s) = exterior s := by - simp only [exterior_eq_exterior_iff_nhdsSet, nhdsSet_exterior] - lemma Inducing.alexandrovDiscrete [AlexandrovDiscrete α] {f : β → α} (h : Inducing f) : AlexandrovDiscrete β where isOpen_sInter S hS := by @@ -210,18 +124,6 @@ lemma Inducing.alexandrovDiscrete [AlexandrovDiscrete α] {f : β → α} (h : I refine ⟨_, isOpen_iInter₂ hU, ?_⟩ simp_rw [preimage_iInter, htU, sInter_eq_biInter] -theorem IsCompact.exterior_iff : IsCompact (exterior s) ↔ IsCompact s := by - simp only [isCompact_iff_finite_subcover] - peel with ι U hUo - simp only [(isOpen_iUnion hUo).exterior_subset, - (isOpen_iUnion fun i ↦ isOpen_iUnion fun _ ↦ hUo i).exterior_subset] - -protected alias ⟨IsCompact.of_exterior, IsCompact.exterior⟩ := IsCompact.exterior_iff - -@[deprecated IsCompact.exterior (since := "2024-09-18")] -lemma Set.Finite.isCompact_exterior (hs : s.Finite) : IsCompact (exterior s) := - hs.isCompact.exterior - end lemma AlexandrovDiscrete.sup {t₁ t₂ : TopologicalSpace α} (_ : @AlexandrovDiscrete α t₁) @@ -283,7 +185,7 @@ instance AlexandrovDiscrete.toFirstCountable : FirstCountableTopology α where instance AlexandrovDiscrete.toLocallyCompactSpace : LocallyCompactSpace α where local_compact_nhds a _U hU := ⟨exterior {a}, isOpen_exterior.mem_nhds <| subset_exterior <| mem_singleton _, - exterior_singleton_subset_iff_mem_nhds.2 hU, (finite_singleton _).isCompact.exterior⟩ + exterior_singleton_subset_iff_mem_nhds.2 hU, isCompact_singleton.exterior⟩ instance Subtype.instAlexandrovDiscrete {p : α → Prop} : AlexandrovDiscrete {a // p a} := inducing_subtype_val.alexandrovDiscrete diff --git a/Mathlib/Topology/Compactness/Exterior.lean b/Mathlib/Topology/Compactness/Exterior.lean new file mode 100644 index 0000000000000..986fcfe09e456 --- /dev/null +++ b/Mathlib/Topology/Compactness/Exterior.lean @@ -0,0 +1,30 @@ +/- +Copyright (c) 2024 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Tactic.Peel +import Mathlib.Topology.Compactness.Compact +import Mathlib.Topology.Exterior + +/-! +# Compactness of the exterior of a set + +In this file we prove that the exterior of a set +(defined as the intersection of all of its neighborhoods) +is a compact set if and only if the original set is a compact set. +-/ + +variable {X : Type*} [TopologicalSpace X] {s : Set X} + +theorem IsCompact.exterior_iff : IsCompact (exterior s) ↔ IsCompact s := by + simp only [isCompact_iff_finite_subcover] + peel with ι U hUo + simp only [(isOpen_iUnion hUo).exterior_subset, + (isOpen_iUnion fun i ↦ isOpen_iUnion fun _ ↦ hUo i).exterior_subset] + +protected alias ⟨IsCompact.of_exterior, IsCompact.exterior⟩ := IsCompact.exterior_iff + +@[deprecated IsCompact.exterior (since := "2024-09-18")] +lemma Set.Finite.isCompact_exterior (hs : s.Finite) : IsCompact (exterior s) := + hs.isCompact.exterior diff --git a/Mathlib/Topology/Defs/Filter.lean b/Mathlib/Topology/Defs/Filter.lean index 7266619675e3b..bf9b961755c3a 100644 --- a/Mathlib/Topology/Defs/Filter.lean +++ b/Mathlib/Topology/Defs/Filter.lean @@ -29,6 +29,12 @@ as well as other definitions that rely on `Filter`s. denoted by `𝓝ˢ s` in the `Topology` scope. A set `t` is called a neighborhood of `s`, if it includes an open set that includes `s`. +* `exterior s`: The *exterior* of a set is the intersection of all its neighborhoods. + In an Alexandrov-discrete space, this is the smallest neighborhood of the set. + + Note that this construction is unnamed in the literature. + We choose the name in analogy to `interior`. + ### Continuity at a point * `ContinuousAt f x`: a function `f` is continuous at a point `x`, @@ -146,6 +152,13 @@ def nhdsSet (s : Set X) : Filter X := @[inherit_doc] scoped[Topology] notation "𝓝ˢ" => nhdsSet +/-- The *exterior* of a set is the intersection of all its neighborhoods. In an Alexandrov-discrete +space, this is the smallest neighborhood of the set. + +Note that this construction is unnamed in the literature. We choose the name in analogy to +`interior`. -/ +def exterior (s : Set X) : Set X := (𝓝ˢ s).ker + /-- A function between topological spaces is continuous at a point `x₀` if `f x` tends to `f x₀` when `x` tends to `x₀`. -/ @[fun_prop] diff --git a/Mathlib/Topology/Exterior.lean b/Mathlib/Topology/Exterior.lean new file mode 100644 index 0000000000000..fcf995f4c441a --- /dev/null +++ b/Mathlib/Topology/Exterior.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2023 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Yury Kudryashov +-/ +import Mathlib.Topology.NhdsSet +import Mathlib.Topology.Inseparable + +/-! +# Exterior of a set + +We define `exterior s` to be the intersection of all neighborhoods of `s`, +see `Topology/Defs/Filter`. +Note that this construction has no standard name in the literature. + +In this file we prove basic properties of this operation. +-/ + +open Set Filter +open scoped Topology + +variable {X : Type*} [TopologicalSpace X] {s t : Set X} {x y : X} + +lemma exterior_singleton_eq_ker_nhds (x : X) : exterior {x} = (𝓝 x).ker := by simp [exterior] + +@[simp] +theorem mem_exterior_singleton : x ∈ exterior {y} ↔ x ⤳ y := by + rw [exterior_singleton_eq_ker_nhds, ker_nhds_eq_specializes, mem_setOf] + +lemma exterior_def (s : Set X) : exterior s = ⋂₀ {t : Set X | IsOpen t ∧ s ⊆ t} := + (hasBasis_nhdsSet _).ker.trans sInter_eq_biInter.symm + +lemma mem_exterior : x ∈ exterior s ↔ ∀ U, IsOpen U → s ⊆ U → x ∈ U := by simp [exterior_def] + +lemma subset_exterior_iff : s ⊆ exterior t ↔ ∀ U, IsOpen U → t ⊆ U → s ⊆ U := by + simp [exterior_def] + +lemma subset_exterior : s ⊆ exterior s := subset_exterior_iff.2 fun _ _ ↦ id + +lemma exterior_minimal (h₁ : s ⊆ t) (h₂ : IsOpen t) : exterior s ⊆ t := by + rw [exterior_def]; exact sInter_subset_of_mem ⟨h₂, h₁⟩ + +lemma IsOpen.exterior_eq (h : IsOpen s) : exterior s = s := + (exterior_minimal Subset.rfl h).antisymm subset_exterior + +lemma IsOpen.exterior_subset (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t := + ⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩ + +@[deprecated (since := "2024-09-18")] alias IsOpen.exterior_subset_iff := IsOpen.exterior_subset + +@[simp] +theorem exterior_iUnion {ι : Sort*} (s : ι → Set X) : + exterior (⋃ i, s i) = ⋃ i, exterior (s i) := by + simp only [exterior, nhdsSet_iUnion, ker_iSup] + +@[simp] +theorem exterior_union (s t : Set X) : exterior (s ∪ t) = exterior s ∪ exterior t := by + simp only [exterior, nhdsSet_union, ker_sup] + +@[simp] +theorem exterior_sUnion (S : Set (Set X)) : exterior (⋃₀ S) = ⋃ s ∈ S, exterior s := by + simp only [sUnion_eq_biUnion, exterior_iUnion] + +theorem mem_exterior_iff_specializes : x ∈ exterior s ↔ ∃ y ∈ s, x ⤳ y := calc + x ∈ exterior s ↔ x ∈ exterior (⋃ y ∈ s, {y}) := by simp + _ ↔ ∃ y ∈ s, x ⤳ y := by + simp only [exterior_iUnion, mem_exterior_singleton, mem_iUnion₂, exists_prop] + +@[mono] lemma exterior_mono : Monotone (exterior : Set X → Set X) := + fun _s _t h ↦ ker_mono <| nhdsSet_mono h + +/-- This name was used to be used for the `Iff` version, +see `exterior_subset_exterior_iff_nhdsSet`. +-/ +@[gcongr] lemma exterior_subset_exterior (h : s ⊆ t) : exterior s ⊆ exterior t := exterior_mono h + +@[simp] lemma exterior_subset_exterior_iff_nhdsSet : exterior s ⊆ exterior t ↔ 𝓝ˢ s ≤ 𝓝ˢ t := by + simp (config := {contextual := true}) only [subset_exterior_iff, (hasBasis_nhdsSet _).ge_iff, + and_imp, IsOpen.mem_nhdsSet, IsOpen.exterior_subset] + +theorem exterior_eq_exterior_iff_nhdsSet : exterior s = exterior t ↔ 𝓝ˢ s = 𝓝ˢ t := by + simp [le_antisymm_iff] + +lemma specializes_iff_exterior_subset : x ⤳ y ↔ exterior {x} ⊆ exterior {y} := by + simp [Specializes] + +@[simp] lemma exterior_empty : exterior (∅ : Set X) = ∅ := isOpen_empty.exterior_eq +@[simp] lemma exterior_univ : exterior (univ : Set X) = univ := isOpen_univ.exterior_eq + +@[simp] lemma exterior_eq_empty : exterior s = ∅ ↔ s = ∅ := + ⟨eq_bot_mono subset_exterior, by rintro rfl; exact exterior_empty⟩ + +@[simp] lemma nhdsSet_exterior (s : Set X) : 𝓝ˢ (exterior s) = 𝓝ˢ s := by + refine le_antisymm ((hasBasis_nhdsSet _).ge_iff.2 ?_) (nhdsSet_mono subset_exterior) + exact fun U ⟨hUo, hsU⟩ ↦ hUo.mem_nhdsSet.2 <| hUo.exterior_subset.2 hsU + +@[simp] lemma exterior_exterior (s : Set X) : exterior (exterior s) = exterior s := by + simp only [exterior_eq_exterior_iff_nhdsSet, nhdsSet_exterior] From 1558c09cd66695027b0f63dcac26dc53af4b99ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 24 Sep 2024 06:31:25 +0000 Subject: [PATCH 116/170] =?UTF-8?q?chore(SetTheory/Ordinal/Basic):=20`lift?= =?UTF-8?q?.initialSeg`=20=E2=86=92=20`liftInitialSeg`=20(#16995)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/SetTheory/Ordinal/Basic.lean | 56 ++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 0c445ec3d40bb..343348306cc66 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -28,9 +28,9 @@ initial segment (or, equivalently, in any way). This total order is well founded * `Ordinal.card o`: the cardinality of an ordinal `o`. * `Ordinal.lift` lifts an ordinal in universe `u` to an ordinal in universe `max u v`. For a version registering additionally that this is an initial segment embedding, see - `Ordinal.lift.initialSeg`. + `Ordinal.liftInitialSeg`. For a version registering that it is a principal segment embedding if `u < v`, see - `Ordinal.lift.principalSeg`. + `Ordinal.liftPrincipalSeg`. * `Ordinal.omega` or `ω` is the order type of `ℕ`. This definition is universe polymorphic: `Ordinal.omega.{u} : Ordinal.{u}` (contrast with `ℕ : Type`, which lives in a specific universe). In some cases the universe level has to be given explicitly. @@ -526,7 +526,7 @@ theorem card_one : card 1 = 1 := mk_eq_one _ -- Porting note: Needed to add universe hint .{u} below /-- The universe lift operation for ordinals, which embeds `Ordinal.{u}` as a proper initial segment of `Ordinal.{v}` for `v > u`. For the initial segment version, - see `lift.initialSeg`. -/ + see `liftInitialSeg`. -/ @[pp_with_univ] def lift (o : Ordinal.{v}) : Ordinal.{max v u} := Quotient.liftOn o (fun w => type <| ULift.down.{u} ⁻¹'o w.r) fun ⟨_, r, _⟩ ⟨_, s, _⟩ ⟨f⟩ => @@ -686,11 +686,19 @@ theorem lt_lift_iff {a : Ordinal.{u}} {b : Ordinal.{max u v}} : /-- Initial segment version of the lift operation on ordinals, embedding `ordinal.{u}` in `ordinal.{v}` as an initial segment when `u ≤ v`. -/ -def lift.initialSeg : @InitialSeg Ordinal.{u} Ordinal.{max u v} (· < ·) (· < ·) := +def liftInitialSeg : @InitialSeg Ordinal.{u} Ordinal.{max u v} (· < ·) (· < ·) := ⟨⟨⟨lift.{v}, fun _ _ => lift_inj.1⟩, lift_lt⟩, fun _ _ h => lift_down (le_of_lt h)⟩ +@[deprecated liftInitialSeg (since := "2024-09-21")] +alias lift.initialSeg := liftInitialSeg + @[simp] -theorem lift.initialSeg_coe : (lift.initialSeg.{u,v} : Ordinal → Ordinal) = lift.{v,u} := +theorem liftInitialSeg_coe : (liftInitialSeg.{u, v} : Ordinal → Ordinal) = lift.{v, u} := + rfl + +set_option linter.deprecated false in +@[deprecated liftInitialSeg_coe (since := "2024-09-21")] +theorem lift.initialSeg_coe : (lift.initialSeg.{u, v} : Ordinal → Ordinal) = lift.{v, u} := rfl /-! ### The first infinite ordinal `omega` -/ @@ -1035,8 +1043,8 @@ theorem univ_umax : univ.{u, max (u + 1) v} = univ.{u, v} := /-- Principal segment version of the lift operation on ordinals, embedding `ordinal.{u}` in `ordinal.{v}` as a principal segment when `u < v`. -/ -def lift.principalSeg : @PrincipalSeg Ordinal.{u} Ordinal.{max (u + 1) v} (· < ·) (· < ·) := - ⟨↑lift.initialSeg.{u, max (u + 1) v}, univ.{u, v}, by +def liftPrincipalSeg : @PrincipalSeg Ordinal.{u} Ordinal.{max (u + 1) v} (· < ·) (· < ·) := + ⟨↑liftInitialSeg.{u, max (u + 1) v}, univ.{u, v}, by refine fun b => inductionOn b ?_; intro β s _ rw [univ, ← lift_umax]; constructor <;> intro h · rw [← lift_id (type s)] at h ⊢ @@ -1065,16 +1073,34 @@ def lift.principalSeg : @PrincipalSeg Ordinal.{u} Ordinal.{max (u + 1) v} (· < intro α r _ exact lift_type_lt.{u, u + 1, max (u + 1) v}.2 ⟨typein.principalSeg r⟩⟩ +@[deprecated liftPrincipalSeg (since := "2024-09-21")] +alias lift.principalSeg := liftPrincipalSeg + @[simp] +theorem liftPrincipalSeg_coe : + (liftPrincipalSeg.{u, v} : Ordinal → Ordinal) = lift.{max (u + 1) v} := + rfl + +set_option linter.deprecated false in +@[deprecated liftPrincipalSeg_coe (since := "2024-09-21")] theorem lift.principalSeg_coe : (lift.principalSeg.{u, v} : Ordinal → Ordinal) = lift.{max (u + 1) v} := rfl --- Porting note: Added universe hints below @[simp] -theorem lift.principalSeg_top : (lift.principalSeg.{u,v}).top = univ.{u,v} := +theorem liftPrincipalSeg_top : (liftPrincipalSeg.{u, v}).top = univ.{u, v} := + rfl + +set_option linter.deprecated false in +@[deprecated liftPrincipalSeg_top (since := "2024-09-21")] +theorem lift.principalSeg_top : (lift.principalSeg.{u, v}).top = univ.{u, v} := rfl +theorem liftPrincipalSeg_top' : liftPrincipalSeg.{u, u + 1}.top = @type Ordinal (· < ·) _ := by + simp only [liftPrincipalSeg_top, univ_id] + +set_option linter.deprecated false in +@[deprecated liftPrincipalSeg_top (since := "2024-09-21")] theorem lift.principalSeg_top' : lift.principalSeg.{u, u + 1}.top = @type Ordinal (· < ·) _ := by simp only [lift.principalSeg_top, univ_id] @@ -1283,8 +1309,8 @@ theorem univ_umax : univ.{u, max (u + 1) v} = univ.{u, v} := congr_fun lift_umax _ theorem lift_lt_univ (c : Cardinal) : lift.{u + 1, u} c < univ.{u, u + 1} := by - simpa only [lift.principalSeg_coe, lift_ord, lift_succ, ord_le, succ_le_iff] using - le_of_lt (lift.principalSeg.{u, u + 1}.lt_top (succ c).ord) + simpa only [liftPrincipalSeg_coe, lift_ord, lift_succ, ord_le, succ_le_iff] using + le_of_lt (liftPrincipalSeg.{u, u + 1}.lt_top (succ c).ord) theorem lift_lt_univ' (c : Cardinal) : lift.{max (u + 1) v, u} c < univ.{u, v} := by have := lift_lt.{_, max (u+1) v}.2 (lift_lt_univ c) @@ -1294,18 +1320,18 @@ theorem lift_lt_univ' (c : Cardinal) : lift.{max (u + 1) v, u} c < univ.{u, v} : @[simp] theorem ord_univ : ord univ.{u, v} = Ordinal.univ.{u, v} := by refine le_antisymm (ord_card_le _) <| le_of_forall_lt fun o h => lt_ord.2 ?_ - have := lift.principalSeg.{u, v}.down.1 (by simpa only [lift.principalSeg_coe] using h) + have := liftPrincipalSeg.{u, v}.down.1 (by simpa only [liftPrincipalSeg_coe] using h) rcases this with ⟨o, h'⟩ - rw [← h', lift.principalSeg_coe, ← lift_card] + rw [← h', liftPrincipalSeg_coe, ← lift_card] apply lift_lt_univ' theorem lt_univ {c} : c < univ.{u, u + 1} ↔ ∃ c', c = lift.{u + 1, u} c' := ⟨fun h => by have := ord_lt_ord.2 h rw [ord_univ] at this - cases' lift.principalSeg.{u, u + 1}.down.1 (by simpa only [lift.principalSeg_top] ) with o e + cases' liftPrincipalSeg.{u, u + 1}.down.1 (by simpa only [liftPrincipalSeg_top] ) with o e have := card_ord c - rw [← e, lift.principalSeg_coe, ← lift_card] at this + rw [← e, liftPrincipalSeg_coe, ← lift_card] at this exact ⟨_, this.symm⟩, fun ⟨c', e⟩ => e.symm ▸ lift_lt_univ _⟩ theorem lt_univ' {c} : c < univ.{u, v} ↔ ∃ c', c = lift.{max (u + 1) v, u} c' := From f4a9481ee46201ea7727583497f3ccc77f15f926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 24 Sep 2024 06:31:26 +0000 Subject: [PATCH 117/170] feat(SetTheory/*): intervals of Cardinal/Ordinal/Nimber are small (#16999) --- Mathlib/SetTheory/Cardinal/Basic.lean | 9 ++++++--- Mathlib/SetTheory/Ordinal/Arithmetic.lean | 15 --------------- Mathlib/SetTheory/Ordinal/Basic.lean | 12 ++++++++++++ Mathlib/SetTheory/Ordinal/Nimber.lean | 11 ++++++----- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index d4ea99f073058..2a607f4838215 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -951,14 +951,17 @@ theorem bddAbove_range {ι : Type u} (f : ι → Cardinal.{max u v}) : BddAbove rintro a ⟨i, rfl⟩ exact le_sum f i⟩ -instance (a : Cardinal.{u}) : Small.{u} (Set.Iic a) := by +instance small_Iic (a : Cardinal.{u}) : Small.{u} (Iic a) := by rw [← mk_out a] apply @small_of_surjective (Set a.out) (Iic #a.out) _ fun x => ⟨#x, mk_set_le x⟩ rintro ⟨x, hx⟩ simpa using le_mk_iff_exists_set.1 hx -instance (a : Cardinal.{u}) : Small.{u} (Set.Iio a) := - small_subset Iio_subset_Iic_self +instance small_Iio (a : Cardinal.{u}) : Small.{u} (Iio a) := small_subset Iio_subset_Iic_self +instance small_Icc (a b : Cardinal.{u}) : Small.{u} (Icc a b) := small_subset Icc_subset_Iic_self +instance small_Ico (a b : Cardinal.{u}) : Small.{u} (Ico a b) := small_subset Ico_subset_Iio_self +instance small_Ioc (a b : Cardinal.{u}) : Small.{u} (Ioc a b) := small_subset Ioc_subset_Iic_self +instance small_Ioo (a b : Cardinal.{u}) : Small.{u} (Ioo a b) := small_subset Ioo_subset_Iio_self /-- A set of cardinals is bounded above iff it's small, i.e. it corresponds to a usual ZFC set. -/ theorem bddAbove_iff_small {s : Set Cardinal.{u}} : BddAbove s ↔ Small.{u} s := diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 6c48281bba80c..3fb5355737b96 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -1306,21 +1306,6 @@ theorem le_sup_shrink_equiv {s : Set Ordinal.{u}} (hs : Small.{u} s) (a) (ha : a -- TODO: move this together with `bddAbove_range`. -instance small_Iio (o : Ordinal.{u}) : Small.{u} (Set.Iio o) := - let f : o.toType → Set.Iio o := - fun x => ⟨typein (α := o.toType) (· < ·) x, typein_lt_self x⟩ - let hf : Surjective f := fun b => - ⟨enum (α := o.toType) (· < ·) ⟨b.val, - by - rw [type_lt] - exact b.prop⟩, - Subtype.ext (typein_enum _ _)⟩ - small_of_surjective hf - -instance small_Iic (o : Ordinal.{u}) : Small.{u} (Set.Iic o) := by - rw [← Iio_succ] - infer_instance - theorem bddAbove_of_small (s : Set Ordinal.{u}) [h : Small.{u} s] : BddAbove s := by obtain ⟨a, ha⟩ := bddAbove_range (fun x => ((@equivShrink s h).symm x).val) use a diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 343348306cc66..0ebca27c90b0b 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -1008,6 +1008,18 @@ noncomputable def enumIsoToType (o : Ordinal) : Set.Iio o ≃o o.toType where @[deprecated (since := "2024-08-26")] alias enumIsoOut := enumIsoToType +instance small_Iio (o : Ordinal.{u}) : Small.{u} (Iio o) := + ⟨_, ⟨(enumIsoToType _).toEquiv⟩⟩ + +instance small_Iic (o : Ordinal.{u}) : Small.{u} (Iic o) := by + rw [← Iio_succ] + exact small_Iio _ + +instance small_Ico (a b : Ordinal.{u}) : Small.{u} (Ico a b) := small_subset Ico_subset_Iio_self +instance small_Icc (a b : Ordinal.{u}) : Small.{u} (Icc a b) := small_subset Icc_subset_Iic_self +instance small_Ioo (a b : Ordinal.{u}) : Small.{u} (Ioo a b) := small_subset Ioo_subset_Iio_self +instance small_Ioc (a b : Ordinal.{u}) : Small.{u} (Ioc a b) := small_subset Ioc_subset_Iic_self + /-- `o.toType` is an `OrderBot` whenever `0 < o`. -/ def toTypeOrderBotOfPos {o : Ordinal} (ho : 0 < o) : OrderBot o.toType where bot_le := enum_zero_le' ho diff --git a/Mathlib/SetTheory/Ordinal/Nimber.lean b/Mathlib/SetTheory/Ordinal/Nimber.lean index e42c8d4e88ac3..538d61ec4400d 100644 --- a/Mathlib/SetTheory/Ordinal/Nimber.lean +++ b/Mathlib/SetTheory/Ordinal/Nimber.lean @@ -138,11 +138,12 @@ protected theorem not_lt_zero (a : Nimber) : ¬ a < 0 := protected theorem pos_iff_ne_zero {a : Nimber} : 0 < a ↔ a ≠ 0 := Ordinal.pos_iff_ne_zero -instance (a : Nimber.{u}) : Small.{u} (Set.Iio a) := - Ordinal.small_Iio a - -instance (a : Nimber.{u}) : Small.{u} (Set.Iic a) := - Ordinal.small_Iic a +instance small_Iio (a : Nimber.{u}) : Small.{u} (Set.Iio a) := Ordinal.small_Iio a +instance small_Iic (a : Nimber.{u}) : Small.{u} (Set.Iic a) := Ordinal.small_Iic a +instance small_Ico (a b : Nimber.{u}) : Small.{u} (Set.Ico a b) := Ordinal.small_Ico a b +instance small_Icc (a b : Nimber.{u}) : Small.{u} (Set.Icc a b) := Ordinal.small_Icc a b +instance small_Ioo (a b : Nimber.{u}) : Small.{u} (Set.Ioo a b) := Ordinal.small_Ioo a b +instance small_Ioc (a b : Nimber.{u}) : Small.{u} (Set.Ioc a b) := Ordinal.small_Ioc a b end Nimber From d6fde790428207c6b9e5b4426fbd3a71993cadda Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 24 Sep 2024 06:31:28 +0000 Subject: [PATCH 118/170] feat(NumberTheory/PrimeCounting): surjective and tendsto (#17006) Co-authored-by: Moritz Firsching --- Mathlib/Data/Nat/Nth.lean | 4 +++ Mathlib/NumberTheory/PrimeCounting.lean | 40 +++++++++++++++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Mathlib/Data/Nat/Nth.lean b/Mathlib/Data/Nat/Nth.lean index 2fe95f6458a83..a9e8888ac5127 100644 --- a/Mathlib/Data/Nat/Nth.lean +++ b/Mathlib/Data/Nat/Nth.lean @@ -303,6 +303,10 @@ theorem count_nth_of_lt_card_finite {n : ℕ} (hp : (setOf p).Finite) (hlt : n < theorem count_nth_of_infinite (hp : (setOf p).Infinite) (n : ℕ) : count p (nth p n) = n := count_nth fun hf => absurd hf hp +theorem surjective_count_of_infinite_setOf (h : {n | p n}.Infinite) : + Function.Surjective (Nat.count p) := + fun n => ⟨nth p n, count_nth_of_infinite h n⟩ + theorem count_nth_succ {n : ℕ} (hn : ∀ hf : (setOf p).Finite, n < hf.toFinset.card) : count p (nth p n + 1) = n + 1 := by rw [count_succ, count_nth hn, if_pos (nth_mem _ hn)] diff --git a/Mathlib/NumberTheory/PrimeCounting.lean b/Mathlib/NumberTheory/PrimeCounting.lean index 92dca84e7b65e..3005d0cb7165a 100644 --- a/Mathlib/NumberTheory/PrimeCounting.lean +++ b/Mathlib/NumberTheory/PrimeCounting.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Bolton Bailey. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bolton Bailey, Ralf Stephan -/ -import Mathlib.Data.Nat.Totient import Mathlib.Data.Nat.Nth +import Mathlib.Data.Nat.Totient import Mathlib.NumberTheory.SmoothNumbers /-! @@ -56,6 +56,10 @@ def primeCounting (n : ℕ) : ℕ := open scoped Nat.Prime +@[simp] +theorem primeCounting_sub_one (n : ℕ) : π (n - 1) = π' n := by + cases n <;> rfl + theorem monotone_primeCounting' : Monotone primeCounting' := count_monotone Prime @@ -66,13 +70,38 @@ theorem monotone_primeCounting : Monotone primeCounting := theorem primeCounting'_nth_eq (n : ℕ) : π' (nth Prime n) = n := count_nth_of_infinite infinite_setOf_prime _ +@[simp] +theorem zeroth_prime_eq_two : nth Prime 0 = 2 := nth_count prime_two + +/-- The `n`th prime is greater or equal to `n + 2`. -/ +theorem add_two_le_nth_prime (n : ℕ) : n + 2 ≤ nth Prime n := + zeroth_prime_eq_two ▸ (nth_strictMono infinite_setOf_prime).add_le_nat n 0 + +theorem surjective_primeCounting' : Function.Surjective π' := + Nat.surjective_count_of_infinite_setOf infinite_setOf_prime + +theorem surjective_primeCounting : Function.Surjective π := by + suffices Function.Surjective (π ∘ fun n => n - 1) from this.of_comp + convert surjective_primeCounting' + ext + exact primeCounting_sub_one _ + +open Filter + +theorem tendsto_primeCounting' : Tendsto π' atTop atTop := by + apply tendsto_atTop_atTop_of_monotone' monotone_primeCounting' + simp [Set.range_iff_surjective.mpr surjective_primeCounting'] + +theorem tensto_primeCounting : Tendsto π atTop atTop := + (tendsto_add_atTop_iff_nat 1).mpr tendsto_primeCounting' + @[simp] theorem prime_nth_prime (n : ℕ) : Prime (nth Prime n) := nth_mem_of_infinite infinite_setOf_prime _ /-- The cardinality of the finset `primesBelow n` equals the counting function `primeCounting'` at `n`. -/ -lemma primesBelow_card_eq_primeCounting' (n : ℕ) : n.primesBelow.card = primeCounting' n := by +theorem primesBelow_card_eq_primeCounting' (n : ℕ) : n.primesBelow.card = primeCounting' n := by simp only [primesBelow, primeCounting'] exact (count_eq_card_filter_range Prime n).symm @@ -98,11 +127,4 @@ theorem primeCounting'_add_le {a k : ℕ} (h0 : 0 < a) (h1 : a < k) (n : ℕ) : rw [add_le_add_iff_left] exact Ico_filter_coprime_le k n h0 -@[simp] -theorem zeroth_prime_eq_two : nth Prime 0 = 2 := nth_count prime_two - -/-- The `n`th prime is greater or equal to `n + 2`. -/ -lemma add_two_le_nth_prime (n : ℕ) : n + 2 ≤ nth Prime n := - zeroth_prime_eq_two ▸ (nth_strictMono infinite_setOf_prime).add_le_nat n 0 - end Nat From 30c481f1821c2b61dad5571b81b0bff368769ab5 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 24 Sep 2024 06:31:29 +0000 Subject: [PATCH 119/170] chore: update name in copyrights (#17074) --- Archive/Examples/IfNormalization/Statement.lean | 2 +- Archive/Examples/IfNormalization/WithoutAesop.lean | 2 +- Archive/Examples/MersennePrimes.lean | 4 ++-- LongestPole/Main.lean | 4 ++-- LongestPole/SpeedCenterJson.lean | 4 ++-- Mathlib/Algebra/Category/AlgebraCat/Basic.lean | 4 ++-- Mathlib/Algebra/Category/AlgebraCat/Limits.lean | 4 ++-- Mathlib/Algebra/Category/FGModuleCat/Limits.lean | 4 ++-- Mathlib/Algebra/Category/Grp/Adjunctions.lean | 4 ++-- Mathlib/Algebra/Category/Grp/Biproducts.lean | 4 ++-- Mathlib/Algebra/Category/Grp/Colimits.lean | 4 ++-- Mathlib/Algebra/Category/Grp/Images.lean | 4 ++-- Mathlib/Algebra/Category/Grp/Limits.lean | 4 ++-- Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean | 4 ++-- Mathlib/Algebra/Category/Grp/Zero.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Algebra.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Biproducts.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Colimits.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/EpiMono.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Images.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Limits.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Monoidal/Symmetric.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Presheaf.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Products.lean | 4 ++-- Mathlib/Algebra/Category/ModuleCat/Projective.lean | 2 +- Mathlib/Algebra/Category/ModuleCat/Simple.lean | 2 +- Mathlib/Algebra/Category/ModuleCat/Tannaka.lean | 4 ++-- Mathlib/Algebra/Category/MonCat/Basic.lean | 4 ++-- Mathlib/Algebra/Category/MonCat/Colimits.lean | 4 ++-- Mathlib/Algebra/Category/MonCat/Limits.lean | 4 ++-- Mathlib/Algebra/Category/Ring/Adjunctions.lean | 4 ++-- Mathlib/Algebra/Category/Ring/Basic.lean | 4 ++-- Mathlib/Algebra/Category/Ring/Colimits.lean | 4 ++-- Mathlib/Algebra/Category/Ring/Limits.lean | 4 ++-- Mathlib/Algebra/FreeAlgebra.lean | 2 +- Mathlib/Algebra/Group/Commute/Hom.lean | 2 +- Mathlib/Algebra/Group/Hom/Basic.lean | 2 +- Mathlib/Algebra/Group/Hom/Defs.lean | 2 +- Mathlib/Algebra/Group/Hom/End.lean | 2 +- Mathlib/Algebra/Group/Hom/Instances.lean | 2 +- Mathlib/Algebra/Group/ULift.lean | 4 ++-- Mathlib/Algebra/GroupWithZero/ULift.lean | 4 ++-- Mathlib/Algebra/HierarchyDesign.lean | 4 ++-- Mathlib/Algebra/Homology/Additive.lean | 4 ++-- Mathlib/Algebra/Homology/Augment.lean | 4 ++-- Mathlib/Algebra/Homology/ComplexShape.lean | 4 ++-- Mathlib/Algebra/Homology/DifferentialObject.lean | 4 ++-- Mathlib/Algebra/Homology/HomologicalBicomplex.lean | 4 ++-- Mathlib/Algebra/Homology/HomologicalComplex.lean | 4 ++-- Mathlib/Algebra/Homology/Homotopy.lean | 4 ++-- Mathlib/Algebra/Homology/HomotopyCategory.lean | 4 ++-- Mathlib/Algebra/Homology/ImageToKernel.lean | 4 ++-- Mathlib/Algebra/Homology/LocalCohomology.lean | 2 +- Mathlib/Algebra/Homology/QuasiIso.lean | 4 ++-- Mathlib/Algebra/Homology/Single.lean | 4 ++-- Mathlib/Algebra/Module/Algebra.lean | 4 ++-- Mathlib/Algebra/Module/ULift.lean | 4 ++-- Mathlib/Algebra/MonoidAlgebra/Basic.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 2 +- Mathlib/Algebra/MvPolynomial/Polynomial.lean | 4 ++-- Mathlib/Algebra/Order/Algebra.lean | 4 ++-- Mathlib/Algebra/Order/Group/Cone.lean | 2 +- Mathlib/Algebra/Order/Interval/Set/Instances.lean | 2 +- Mathlib/Algebra/Order/Star/Basic.lean | 4 ++-- Mathlib/Algebra/Order/Sub/Prod.lean | 4 ++-- Mathlib/Algebra/Polynomial/AlgebraMap.lean | 2 +- Mathlib/Algebra/Polynomial/Basic.lean | 2 +- Mathlib/Algebra/Polynomial/Coeff.lean | 2 +- Mathlib/Algebra/Polynomial/Degree/Definitions.lean | 2 +- Mathlib/Algebra/Polynomial/Degree/Lemmas.lean | 2 +- Mathlib/Algebra/Polynomial/Derivative.lean | 2 +- Mathlib/Algebra/Polynomial/Div.lean | 2 +- Mathlib/Algebra/Polynomial/Eval.lean | 2 +- Mathlib/Algebra/Polynomial/FieldDivision.lean | 2 +- Mathlib/Algebra/Polynomial/Identities.lean | 2 +- Mathlib/Algebra/Polynomial/Induction.lean | 2 +- Mathlib/Algebra/Polynomial/Inductions.lean | 2 +- Mathlib/Algebra/Polynomial/Monic.lean | 2 +- Mathlib/Algebra/Polynomial/Monomial.lean | 2 +- Mathlib/Algebra/Polynomial/RingDivision.lean | 2 +- Mathlib/Algebra/Polynomial/Roots.lean | 2 +- Mathlib/Algebra/Ring/ULift.lean | 4 ++-- Mathlib/Algebra/RingQuot.lean | 4 ++-- Mathlib/Algebra/Star/Basic.lean | 4 ++-- Mathlib/Algebra/Star/CHSH.lean | 4 ++-- Mathlib/Algebra/Star/Subalgebra.lean | 4 ++-- Mathlib/AlgebraicGeometry/Scheme.lean | 4 ++-- Mathlib/AlgebraicGeometry/Spec.lean | 4 ++-- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 4 ++-- Mathlib/AlgebraicTopology/MooreComplex.lean | 4 ++-- Mathlib/AlgebraicTopology/SimplexCategory.lean | 4 ++-- Mathlib/AlgebraicTopology/SimplicialObject.lean | 4 ++-- Mathlib/AlgebraicTopology/SimplicialSet.lean | 4 ++-- Mathlib/AlgebraicTopology/SingularSet.lean | 2 +- Mathlib/Analysis/Convex/Caratheodory.lean | 4 ++-- Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean | 4 ++-- Mathlib/Analysis/SpecialFunctions/Bernstein.lean | 4 ++-- Mathlib/Analysis/VonNeumannAlgebra/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Abelian/Basic.lean | 2 +- Mathlib/CategoryTheory/Abelian/Ext.lean | 4 ++-- Mathlib/CategoryTheory/Abelian/FunctorCategory.lean | 4 ++-- Mathlib/CategoryTheory/Abelian/Images.lean | 2 +- Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean | 2 +- Mathlib/CategoryTheory/Abelian/LeftDerived.lean | 4 ++-- Mathlib/CategoryTheory/Abelian/Opposite.lean | 4 ++-- Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean | 2 +- Mathlib/CategoryTheory/Abelian/RightDerived.lean | 2 +- Mathlib/CategoryTheory/Abelian/Transfer.lean | 4 ++-- Mathlib/CategoryTheory/Adjunction/FullyFaithful.lean | 4 ++-- Mathlib/CategoryTheory/Adjunction/Restrict.lean | 4 ++-- Mathlib/CategoryTheory/Bicategory/End.lean | 4 ++-- Mathlib/CategoryTheory/Bicategory/SingleObj.lean | 4 ++-- Mathlib/CategoryTheory/Category/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Category/Cat/Limit.lean | 4 ++-- Mathlib/CategoryTheory/Category/GaloisConnection.lean | 4 ++-- Mathlib/CategoryTheory/Category/Pairwise.lean | 4 ++-- Mathlib/CategoryTheory/Category/Preorder.lean | 4 ++-- Mathlib/CategoryTheory/Category/Quiv.lean | 4 ++-- Mathlib/CategoryTheory/Category/RelCat.lean | 4 ++-- Mathlib/CategoryTheory/Closed/Monoidal.lean | 4 ++-- Mathlib/CategoryTheory/CommSq.lean | 4 ++-- Mathlib/CategoryTheory/Comma/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Comma/StructuredArrow.lean | 4 ++-- Mathlib/CategoryTheory/ConcreteCategory/Basic.lean | 4 ++-- Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean | 4 ++-- Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean | 4 ++-- Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean | 4 ++-- Mathlib/CategoryTheory/Core.lean | 4 ++-- Mathlib/CategoryTheory/DifferentialObject.lean | 4 ++-- Mathlib/CategoryTheory/DiscreteCategory.lean | 4 ++-- Mathlib/CategoryTheory/Elements.lean | 4 ++-- Mathlib/CategoryTheory/Elementwise.lean | 4 ++-- Mathlib/CategoryTheory/Endofunctor/Algebra.lean | 2 +- Mathlib/CategoryTheory/Endomorphism.lean | 2 +- Mathlib/CategoryTheory/Enriched/Basic.lean | 4 ++-- Mathlib/CategoryTheory/EpiMono.lean | 2 +- Mathlib/CategoryTheory/EqToHom.lean | 2 +- Mathlib/CategoryTheory/Equivalence.lean | 4 ++-- Mathlib/CategoryTheory/EssentiallySmall.lean | 4 ++-- Mathlib/CategoryTheory/Filtered/Basic.lean | 2 +- Mathlib/CategoryTheory/FinCategory/AsType.lean | 4 ++-- Mathlib/CategoryTheory/FinCategory/Basic.lean | 4 ++-- Mathlib/CategoryTheory/FullSubcategory.lean | 4 ++-- Mathlib/CategoryTheory/Functor/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Functor/Category.lean | 4 ++-- Mathlib/CategoryTheory/Functor/Const.lean | 4 ++-- Mathlib/CategoryTheory/Functor/Currying.lean | 4 ++-- Mathlib/CategoryTheory/Functor/FullyFaithful.lean | 4 ++-- Mathlib/CategoryTheory/Functor/Functorial.lean | 4 ++-- Mathlib/CategoryTheory/Functor/Hom.lean | 2 +- Mathlib/CategoryTheory/GradedObject.lean | 4 ++-- Mathlib/CategoryTheory/Grothendieck.lean | 4 ++-- Mathlib/CategoryTheory/Groupoid.lean | 2 +- Mathlib/CategoryTheory/Iso.lean | 4 ++-- Mathlib/CategoryTheory/Limits/ColimitLimit.lean | 4 ++-- Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Cones.lean | 4 ++-- .../Limits/Constructions/LimitsOfProductsAndEqualizers.lean | 2 +- .../CategoryTheory/Limits/Constructions/ZeroObjects.lean | 4 ++-- .../Limits/FilteredColimitCommutesFiniteLimit.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Final.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Fubini.lean | 4 ++-- Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Limits/HasLimits.lean | 4 ++-- Mathlib/CategoryTheory/Limits/IsLimit.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Lattice.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Opposites.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Pi.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Preserves/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Preserves/Filtered.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Preserves/Limits.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean | 4 ++-- .../CategoryTheory/Limits/Preserves/Shapes/Products.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean | 2 +- Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/FiniteProducts.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Images.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Products.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Pullback/Assoc.lean | 2 +- Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Pullback/Cospan.lean | 4 ++-- .../CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Pullback/Iso.lean | 2 +- Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean | 2 +- Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean | 2 +- .../CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Terminal.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/Types.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Types.lean | 4 ++-- Mathlib/CategoryTheory/Limits/TypesFiltered.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Unit.lean | 4 ++-- Mathlib/CategoryTheory/Limits/Yoneda.lean | 4 ++-- Mathlib/CategoryTheory/Linear/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Linear/FunctorCategory.lean | 4 ++-- Mathlib/CategoryTheory/Linear/LinearFunctor.lean | 4 ++-- Mathlib/CategoryTheory/Linear/Yoneda.lean | 4 ++-- Mathlib/CategoryTheory/Monad/Adjunction.lean | 4 ++-- Mathlib/CategoryTheory/Monad/Algebra.lean | 4 ++-- Mathlib/CategoryTheory/Monad/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Monad/Limits.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Bimod.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Braided/Opposite.lean | 2 +- Mathlib/CategoryTheory/Monoidal/Category.lean | 2 +- Mathlib/CategoryTheory/Monoidal/Center.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean | 2 +- Mathlib/CategoryTheory/Monoidal/CommMon_.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Discrete.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/End.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Functor.lean | 2 +- Mathlib/CategoryTheory/Monoidal/FunctorCategory.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Functorial.lean | 4 ++-- .../CategoryTheory/Monoidal/Internal/FunctorCategory.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Internal/Limits.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Internal/Module.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Internal/Types.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Limits.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Linear.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Mod_.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Mon_.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/NaturalTransformation.lean | 4 ++-- .../Monoidal/OfChosenFiniteProducts/Basic.lean | 4 ++-- .../Monoidal/OfChosenFiniteProducts/Symmetric.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Opposite.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Preadditive.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Rigid/FunctorCategory.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Rigid/OfEquivalence.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Tor.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Transport.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Types/Basic.lean | 2 +- Mathlib/CategoryTheory/Monoidal/Types/Coyoneda.lean | 2 +- Mathlib/CategoryTheory/Monoidal/Types/Symmetric.lean | 2 +- Mathlib/CategoryTheory/NatIso.lean | 4 ++-- Mathlib/CategoryTheory/NatTrans.lean | 4 ++-- Mathlib/CategoryTheory/Noetherian.lean | 4 ++-- Mathlib/CategoryTheory/Opposites.lean | 4 ++-- Mathlib/CategoryTheory/PEmpty.lean | 4 ++-- Mathlib/CategoryTheory/PUnit.lean | 4 ++-- Mathlib/CategoryTheory/PathCategory.lean | 4 ++-- Mathlib/CategoryTheory/Pi/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean | 2 +- Mathlib/CategoryTheory/Preadditive/Biproducts.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/HomOrthogonal.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean | 2 +- Mathlib/CategoryTheory/Preadditive/Mat.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/Opposite.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/Projective.lean | 2 +- .../CategoryTheory/Preadditive/ProjectiveResolution.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/Schur.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/SingleObj.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/Yoneda/Injective.lean | 2 +- Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean | 2 +- Mathlib/CategoryTheory/Products/Associator.lean | 4 ++-- Mathlib/CategoryTheory/Products/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Products/Bifunctor.lean | 4 ++-- Mathlib/CategoryTheory/Shift/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Simple.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/FactorThru.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/Lattice.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/Limits.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/MonoOver.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/Types.lean | 4 ++-- Mathlib/CategoryTheory/Subobject/WellPowered.lean | 4 ++-- Mathlib/CategoryTheory/Sums/Associator.lean | 4 ++-- Mathlib/CategoryTheory/Sums/Basic.lean | 4 ++-- Mathlib/CategoryTheory/Thin.lean | 4 ++-- Mathlib/CategoryTheory/Types.lean | 4 ++-- Mathlib/CategoryTheory/UnivLE.lean | 4 ++-- Mathlib/CategoryTheory/Whiskering.lean | 4 ++-- Mathlib/CategoryTheory/Yoneda.lean | 4 ++-- Mathlib/Combinatorics/Quiver/Basic.lean | 2 +- Mathlib/Combinatorics/Quiver/Path.lean | 2 +- Mathlib/Control/EquivFunctor.lean | 4 ++-- Mathlib/Control/EquivFunctor/Instances.lean | 4 ++-- Mathlib/Control/ULift.lean | 4 ++-- Mathlib/Data/Complex/Order.lean | 4 ++-- Mathlib/Data/Countable/Small.lean | 4 ++-- Mathlib/Data/Finset/Fin.lean | 2 +- Mathlib/Data/Finset/Functor.lean | 2 +- Mathlib/Data/Finsupp/Basic.lean | 2 +- Mathlib/Data/Finsupp/Defs.lean | 2 +- Mathlib/Data/Finsupp/Pointwise.lean | 4 ++-- Mathlib/Data/List/EditDistance/Bounds.lean | 4 ++-- Mathlib/Data/List/EditDistance/Defs.lean | 4 ++-- Mathlib/Data/List/EditDistance/Estimator.lean | 4 ++-- Mathlib/Data/List/FinRange.lean | 2 +- Mathlib/Data/List/Intervals.lean | 4 ++-- Mathlib/Data/List/Lattice.lean | 2 +- Mathlib/Data/List/Range.lean | 2 +- Mathlib/Data/MLList/BestFirst.lean | 4 ++-- Mathlib/Data/MLList/Dedup.lean | 4 ++-- Mathlib/Data/MLList/DepthFirst.lean | 4 ++-- Mathlib/Data/MLList/IO.lean | 4 ++-- Mathlib/Data/MLList/Split.lean | 4 ++-- Mathlib/Data/Matrix/Basis.lean | 2 +- Mathlib/Data/Matrix/DMatrix.lean | 4 ++-- Mathlib/Data/Nat/Count.lean | 2 +- Mathlib/Data/Nat/Digits.lean | 4 ++-- Mathlib/Data/Nat/Nth.lean | 2 +- Mathlib/Data/Opposite.lean | 4 ++-- Mathlib/Data/PSigma/Order.lean | 4 ++-- Mathlib/Data/Prod/Lex.lean | 4 ++-- Mathlib/Data/Set/Operations.lean | 2 +- Mathlib/Data/Vector/Zip.lean | 4 ++-- Mathlib/Deprecated/HashMap.lean | 4 ++-- Mathlib/Deprecated/Subgroup.lean | 2 +- Mathlib/Geometry/RingedSpace/PresheafedSpace.lean | 4 ++-- .../Geometry/RingedSpace/PresheafedSpace/HasColimits.lean | 4 ++-- Mathlib/Geometry/RingedSpace/SheafedSpace.lean | 4 ++-- Mathlib/Geometry/RingedSpace/Stalks.lean | 4 ++-- Mathlib/GroupTheory/Coset/Basic.lean | 2 +- Mathlib/GroupTheory/Coset/Card.lean | 2 +- Mathlib/Lean/CoreM.lean | 4 ++-- Mathlib/Lean/Expr.lean | 2 +- Mathlib/Lean/Expr/Basic.lean | 2 +- Mathlib/Lean/Expr/ReplaceRec.lean | 2 +- Mathlib/Lean/LocalContext.lean | 4 ++-- Mathlib/Lean/Meta/Basic.lean | 4 ++-- Mathlib/Lean/Meta/DiscrTree.lean | 4 ++-- Mathlib/Lean/Meta/Simp.lean | 4 ++-- Mathlib/Lean/Name.lean | 4 ++-- Mathlib/LinearAlgebra/Dimension/Basic.lean | 2 +- Mathlib/LinearAlgebra/Dimension/Constructions.lean | 2 +- Mathlib/LinearAlgebra/Dimension/DivisionRing.lean | 2 +- Mathlib/LinearAlgebra/Dimension/Finite.lean | 2 +- Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean | 4 ++-- Mathlib/LinearAlgebra/InvariantBasisNumber.lean | 2 +- Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean | 4 ++-- Mathlib/LinearAlgebra/Matrix/InvariantBasisNumber.lean | 4 ++-- Mathlib/LinearAlgebra/TensorProduct/Tower.lean | 4 ++-- Mathlib/Logic/Equiv/Functor.lean | 2 +- Mathlib/Logic/Small/Basic.lean | 4 ++-- Mathlib/Logic/Small/Defs.lean | 4 ++-- Mathlib/Logic/Small/Group.lean | 4 ++-- Mathlib/Logic/Small/List.lean | 4 ++-- Mathlib/Logic/Small/Module.lean | 4 ++-- Mathlib/Logic/Small/Ring.lean | 4 ++-- Mathlib/Logic/UnivLE.lean | 4 ++-- Mathlib/NumberTheory/LucasLehmer.lean | 6 +++--- Mathlib/Order/Estimator.lean | 4 ++-- Mathlib/Order/Interval/Finset/Basic.lean | 4 ++-- Mathlib/Order/Interval/Set/Image.lean | 4 ++-- Mathlib/Order/PartialSups.lean | 4 ++-- Mathlib/RepresentationTheory/Action/Basic.lean | 4 ++-- Mathlib/RepresentationTheory/Action/Concrete.lean | 4 ++-- Mathlib/RepresentationTheory/Action/Limits.lean | 4 ++-- Mathlib/RepresentationTheory/Action/Monoidal.lean | 4 ++-- Mathlib/RepresentationTheory/FDRep.lean | 4 ++-- Mathlib/RepresentationTheory/Maschke.lean | 4 ++-- Mathlib/RepresentationTheory/Rep.lean | 4 ++-- Mathlib/RingTheory/Fintype.lean | 4 ++-- Mathlib/RingTheory/MatrixAlgebra.lean | 4 ++-- Mathlib/RingTheory/Polynomial/Bernstein.lean | 4 ++-- Mathlib/RingTheory/Polynomial/IntegralNormalization.lean | 2 +- Mathlib/RingTheory/Polynomial/Pochhammer.lean | 4 ++-- Mathlib/RingTheory/PolynomialAlgebra.lean | 4 ++-- Mathlib/RingTheory/TensorProduct/Basic.lean | 4 ++-- Mathlib/SetTheory/Game/Basic.lean | 2 +- Mathlib/SetTheory/Game/Domineering.lean | 4 ++-- Mathlib/SetTheory/Game/PGame.lean | 2 +- Mathlib/SetTheory/Game/Short.lean | 4 ++-- Mathlib/SetTheory/Game/State.lean | 4 ++-- Mathlib/SetTheory/Surreal/Basic.lean | 2 +- Mathlib/SetTheory/Surreal/Multiplication.lean | 2 +- Mathlib/Tactic/Abel.lean | 2 +- Mathlib/Tactic/ApplyCongr.lean | 4 ++-- Mathlib/Tactic/ApplyFun.lean | 2 +- Mathlib/Tactic/CategoryTheory/Coherence.lean | 2 +- Mathlib/Tactic/CategoryTheory/Elementwise.lean | 6 +++--- Mathlib/Tactic/CategoryTheory/MonoidalComp.lean | 2 +- Mathlib/Tactic/CategoryTheory/Reassoc.lean | 4 ++-- Mathlib/Tactic/CategoryTheory/Slice.lean | 4 ++-- Mathlib/Tactic/Common.lean | 4 ++-- Mathlib/Tactic/Constructor.lean | 4 ++-- Mathlib/Tactic/Convert.lean | 4 ++-- Mathlib/Tactic/FinCases.lean | 2 +- Mathlib/Tactic/Generalize.lean | 2 +- Mathlib/Tactic/Hint.lean | 4 ++-- Mathlib/Tactic/IntervalCases.lean | 4 ++-- Mathlib/Tactic/NoncommRing.lean | 2 +- Mathlib/Tactic/Propose.lean | 4 ++-- Mathlib/Tactic/Relation/Symm.lean | 4 ++-- Mathlib/Tactic/RewriteSearch.lean | 2 +- Mathlib/Tactic/Says.lean | 4 ++-- Mathlib/Tactic/SlimCheck.lean | 2 +- Mathlib/Tactic/SuccessIfFailWithMsg.lean | 2 +- Mathlib/Topology/Algebra/Algebra.lean | 4 ++-- Mathlib/Topology/Algebra/Algebra/Rat.lean | 4 ++-- Mathlib/Topology/Algebra/Field.lean | 2 +- Mathlib/Topology/Category/TopCat/Adjunctions.lean | 2 +- Mathlib/Topology/Category/TopCat/Basic.lean | 4 ++-- Mathlib/Topology/Category/TopCat/Limits/Basic.lean | 4 ++-- Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean | 4 ++-- Mathlib/Topology/Category/TopCat/Limits/Products.lean | 4 ++-- Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean | 4 ++-- Mathlib/Topology/Category/TopCat/OpenNhds.lean | 4 ++-- Mathlib/Topology/Category/TopCat/Opens.lean | 4 ++-- Mathlib/Topology/Category/TopCommRingCat.lean | 4 ++-- Mathlib/Topology/Category/UniformSpace.lean | 4 ++-- Mathlib/Topology/ContinuousFunction/Algebra.lean | 4 ++-- Mathlib/Topology/ContinuousFunction/Compact.lean | 4 ++-- Mathlib/Topology/ContinuousFunction/Ordered.lean | 4 ++-- Mathlib/Topology/ContinuousFunction/Polynomial.lean | 4 ++-- Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean | 4 ++-- Mathlib/Topology/ContinuousFunction/Weierstrass.lean | 4 ++-- Mathlib/Topology/Sheaves/Forget.lean | 4 ++-- Mathlib/Topology/Sheaves/Limits.lean | 4 ++-- Mathlib/Topology/Sheaves/LocalPredicate.lean | 4 ++-- Mathlib/Topology/Sheaves/Presheaf.lean | 4 ++-- Mathlib/Topology/Sheaves/PresheafOfFunctions.lean | 4 ++-- Mathlib/Topology/Sheaves/Sheaf.lean | 4 ++-- .../Topology/Sheaves/SheafCondition/EqualizerProducts.lean | 4 ++-- Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean | 4 ++-- .../Sheaves/SheafCondition/PairwiseIntersections.lean | 4 ++-- Mathlib/Topology/Sheaves/SheafOfFunctions.lean | 4 ++-- Mathlib/Topology/Sheaves/Sheafify.lean | 4 ++-- Mathlib/Topology/Sheaves/Stalks.lean | 4 ++-- Mathlib/Topology/UnitInterval.lean | 2 +- Mathlib/Util/AddRelatedDecl.lean | 4 ++-- Mathlib/Util/AssertExists.lean | 4 ++-- Mathlib/Util/CountHeartbeats.lean | 4 ++-- Mathlib/Util/LongNames.lean | 4 ++-- Mathlib/Util/Qq.lean | 4 ++-- Mathlib/Util/SynthesizeUsing.lean | 4 ++-- docs/100.yaml | 4 ++-- test/interval_cases.lean | 4 ++-- test/solve_by_elim/basic.lean | 4 ++-- test/solve_by_elim/instances.lean | 4 ++-- 442 files changed, 781 insertions(+), 781 deletions(-) diff --git a/Archive/Examples/IfNormalization/Statement.lean b/Archive/Examples/IfNormalization/Statement.lean index dd642ec3af911..283f4eabf91e3 100644 --- a/Archive/Examples/IfNormalization/Statement.lean +++ b/Archive/Examples/IfNormalization/Statement.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Lean FRO LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ /-! diff --git a/Archive/Examples/IfNormalization/WithoutAesop.lean b/Archive/Examples/IfNormalization/WithoutAesop.lean index 13d0eb001998c..1ac14973a5106 100644 --- a/Archive/Examples/IfNormalization/WithoutAesop.lean +++ b/Archive/Examples/IfNormalization/WithoutAesop.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Scott Morrison +Authors: Chris Hughes, Kim Morrison -/ import Archive.Examples.IfNormalization.Statement import Mathlib.Algebra.Order.Monoid.Canonical.Defs diff --git a/Archive/Examples/MersennePrimes.lean b/Archive/Examples/MersennePrimes.lean index e10d955eb51ee..a19f23f8431d4 100644 --- a/Archive/Examples/MersennePrimes.lean +++ b/Archive/Examples/MersennePrimes.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.NumberTheory.LucasLehmer diff --git a/LongestPole/Main.lean b/LongestPole/Main.lean index 4c21dc471afe4..b4abb23680785 100644 --- a/LongestPole/Main.lean +++ b/LongestPole/Main.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import ImportGraph import Mathlib.Data.String.Defs diff --git a/LongestPole/SpeedCenterJson.lean b/LongestPole/SpeedCenterJson.lean index 63cf423acecec..20a39f872dd0c 100644 --- a/LongestPole/SpeedCenterJson.lean +++ b/LongestPole/SpeedCenterJson.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Lean.Data.Json open Lean diff --git a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean index 6d3c2563e4879..e0919abefa13d 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.FreeAlgebra diff --git a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean index bdbde8808325a..a2f702f99e183 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.AlgebraCat.Basic import Mathlib.Algebra.Category.ModuleCat.Basic diff --git a/Mathlib/Algebra/Category/FGModuleCat/Limits.lean b/Mathlib/Algebra/Category/FGModuleCat/Limits.lean index 8faee2b976d4c..3e5af1918343b 100644 --- a/Mathlib/Algebra/Category/FGModuleCat/Limits.lean +++ b/Mathlib/Algebra/Category/FGModuleCat/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.FGModuleCat.Basic import Mathlib.Algebra.Category.ModuleCat.Limits diff --git a/Mathlib/Algebra/Category/Grp/Adjunctions.lean b/Mathlib/Algebra/Category/Grp/Adjunctions.lean index c7270679aa6c1..d3443fcb9cfc5 100644 --- a/Mathlib/Algebra/Category/Grp/Adjunctions.lean +++ b/Mathlib/Algebra/Category/Grp/Adjunctions.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johannes Hölzl +Authors: Kim Morrison, Johannes Hölzl -/ import Mathlib.Algebra.Category.Grp.Preadditive import Mathlib.GroupTheory.FreeAbelianGroup diff --git a/Mathlib/Algebra/Category/Grp/Biproducts.lean b/Mathlib/Algebra/Category/Grp/Biproducts.lean index 343c5d74d0527..a45ba714db4a0 100644 --- a/Mathlib/Algebra/Category/Grp/Biproducts.lean +++ b/Mathlib/Algebra/Category/Grp/Biproducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Pi.Lemmas import Mathlib.Algebra.Category.Grp.Preadditive diff --git a/Mathlib/Algebra/Category/Grp/Colimits.lean b/Mathlib/Algebra/Category/Grp/Colimits.lean index a53daac3791a2..52e9b257663ec 100644 --- a/Mathlib/Algebra/Category/Grp/Colimits.lean +++ b/Mathlib/Algebra/Category/Grp/Colimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Grp.Preadditive import Mathlib.CategoryTheory.Limits.Shapes.Kernels diff --git a/Mathlib/Algebra/Category/Grp/Images.lean b/Mathlib/Algebra/Category/Grp/Images.lean index 5dd6fd3f51b21..e3f6641b97ec8 100644 --- a/Mathlib/Algebra/Category/Grp/Images.lean +++ b/Mathlib/Algebra/Category/Grp/Images.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Grp.Abelian import Mathlib.CategoryTheory.Limits.Shapes.Images diff --git a/Mathlib/Algebra/Category/Grp/Limits.lean b/Mathlib/Algebra/Category/Grp/Limits.lean index 1f73a158c1bf6..0763ecc4606e9 100644 --- a/Mathlib/Algebra/Category/Grp/Limits.lean +++ b/Mathlib/Algebra/Category/Grp/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.MonCat.Limits import Mathlib.Algebra.Category.Grp.ForgetCorepresentable diff --git a/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean b/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean index fd9a529d37985..242349db0fa0c 100644 --- a/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean +++ b/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Basic diff --git a/Mathlib/Algebra/Category/Grp/Zero.lean b/Mathlib/Algebra/Category/Grp/Zero.lean index 7ecca001e70ea..188eb7bd2216a 100644 --- a/Mathlib/Algebra/Category/Grp/Zero.lean +++ b/Mathlib/Algebra/Category/Grp/Zero.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Grp.Basic import Mathlib.CategoryTheory.Limits.Shapes.ZeroObjects diff --git a/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean b/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean index 9035d34b23389..5fbd14b8fb7c0 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johan Commelin +Authors: Kim Morrison, Johan Commelin -/ import Mathlib.Algebra.Category.ModuleCat.Monoidal.Basic import Mathlib.CategoryTheory.Monoidal.Functorial diff --git a/Mathlib/Algebra/Category/ModuleCat/Algebra.lean b/Mathlib/Algebra/Category/ModuleCat/Algebra.lean index c350e298ae22e..96c3070180a88 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Algebra.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Algebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Algebra.RestrictScalars import Mathlib.CategoryTheory.Linear.Basic diff --git a/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean b/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean index 276eafcbb77e3..445b26e61ac33 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Pi.Lemmas import Mathlib.CategoryTheory.Limits.Shapes.Biproducts diff --git a/Mathlib/Algebra/Category/ModuleCat/Colimits.lean b/Mathlib/Algebra/Category/ModuleCat/Colimits.lean index ae030fd209955..dd77562189b3e 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Colimits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Colimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou +Authors: Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.CategoryTheory.ConcreteCategory.Elementwise diff --git a/Mathlib/Algebra/Category/ModuleCat/EpiMono.lean b/Mathlib/Algebra/Category/ModuleCat/EpiMono.lean index d6f7847ecf6bc..ce1d6cca433f8 100644 --- a/Mathlib/Algebra/Category/ModuleCat/EpiMono.lean +++ b/Mathlib/Algebra/Category/ModuleCat/EpiMono.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.LinearAlgebra.Quotient import Mathlib.Algebra.Category.ModuleCat.Basic diff --git a/Mathlib/Algebra/Category/ModuleCat/Images.lean b/Mathlib/Algebra/Category/ModuleCat/Images.lean index 78b8b35d12247..f08f291b4ebfa 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Images.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Images.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Abelian import Mathlib.CategoryTheory.Limits.Shapes.Images diff --git a/Mathlib/Algebra/Category/ModuleCat/Limits.lean b/Mathlib/Algebra/Category/ModuleCat/Limits.lean index 27b1d3ca656ff..5ad9e49af4722 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Limits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.Algebra.Category.Grp.Limits diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean index 666c67174d69b..cad418c48ab2a 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kevin Buzzard, Scott Morrison, Jakob von Raumer +Authors: Kevin Buzzard, Kim Morrison, Jakob von Raumer -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.LinearAlgebra.TensorProduct.Basic diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean index 9f8d72c55ebd4..55bbfb7b8390c 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kevin Buzzard, Scott Morrison, Jakob von Raumer +Authors: Kevin Buzzard, Kim Morrison, Jakob von Raumer -/ import Mathlib.CategoryTheory.Closed.Monoidal import Mathlib.CategoryTheory.Linear.Yoneda diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Symmetric.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Symmetric.lean index 77fe97befb141..75e4669e16efc 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Symmetric.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Symmetric.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kevin Buzzard, Scott Morrison, Jakob von Raumer +Authors: Kevin Buzzard, Kim Morrison, Jakob von Raumer -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.Algebra.Category.ModuleCat.Monoidal.Basic diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean index 5a9b76b43035b..ecc5852be993d 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.ChangeOfRings import Mathlib.Algebra.Category.Ring.Basic diff --git a/Mathlib/Algebra/Category/ModuleCat/Products.lean b/Mathlib/Algebra/Category/ModuleCat/Products.lean index b4aa2e92eb57f..b986cea15a7f5 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Products.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Products.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.LinearAlgebra.Pi diff --git a/Mathlib/Algebra/Category/ModuleCat/Projective.lean b/Mathlib/Algebra/Category/ModuleCat/Projective.lean index cb26babea2730..7cc29fe3e1107 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Projective.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Projective.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.EpiMono import Mathlib.Algebra.Module.Projective diff --git a/Mathlib/Algebra/Category/ModuleCat/Simple.lean b/Mathlib/Algebra/Category/ModuleCat/Simple.lean index f693c5fcbc18c..dcccbac0230b4 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Simple.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Simple.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Pierre-Alexandre Bazin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Pierre-Alexandre Bazin, Scott Morrison +Authors: Pierre-Alexandre Bazin, Kim Morrison -/ import Mathlib.CategoryTheory.Simple import Mathlib.Algebra.Category.ModuleCat.Subobject diff --git a/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean b/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean index 747def447779c..3d2e15121ab7e 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.LinearAlgebra.Span diff --git a/Mathlib/Algebra/Category/MonCat/Basic.lean b/Mathlib/Algebra/Category/MonCat/Basic.lean index d4510713aa6c0..22bdae9208498 100644 --- a/Mathlib/Algebra/Category/MonCat/Basic.lean +++ b/Mathlib/Algebra/Category/MonCat/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.ConcreteCategory.BundledHom import Mathlib.Algebra.PUnitInstances.Algebra diff --git a/Mathlib/Algebra/Category/MonCat/Colimits.lean b/Mathlib/Algebra/Category/MonCat/Colimits.lean index 98bd6071b109b..bfb19dcc5a1bc 100644 --- a/Mathlib/Algebra/Category/MonCat/Colimits.lean +++ b/Mathlib/Algebra/Category/MonCat/Colimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.MonCat.Basic import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/Algebra/Category/MonCat/Limits.lean b/Mathlib/Algebra/Category/MonCat/Limits.lean index 0de870438eedb..77a05ad7f091f 100644 --- a/Mathlib/Algebra/Category/MonCat/Limits.lean +++ b/Mathlib/Algebra/Category/MonCat/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.MonCat.Basic import Mathlib.Algebra.Group.Pi.Lemmas diff --git a/Mathlib/Algebra/Category/Ring/Adjunctions.lean b/Mathlib/Algebra/Category/Ring/Adjunctions.lean index 49cbc29469c4e..7e9619ecea87c 100644 --- a/Mathlib/Algebra/Category/Ring/Adjunctions.lean +++ b/Mathlib/Algebra/Category/Ring/Adjunctions.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johannes Hölzl +Authors: Kim Morrison, Johannes Hölzl -/ import Mathlib.Algebra.Category.Ring.Basic import Mathlib.Algebra.MvPolynomial.CommRing diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index f195911a46493..59221b72fb4e2 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johannes Hölzl, Yury Kudryashov +Authors: Kim Morrison, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Category.Grp.Basic import Mathlib.CategoryTheory.ConcreteCategory.ReflectsIso diff --git a/Mathlib/Algebra/Category/Ring/Colimits.lean b/Mathlib/Algebra/Category/Ring/Colimits.lean index 5d7cc51769fd3..b2c1204a2af62 100644 --- a/Mathlib/Algebra/Category/Ring/Colimits.lean +++ b/Mathlib/Algebra/Category/Ring/Colimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Ring.Basic import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/Algebra/Category/Ring/Limits.lean b/Mathlib/Algebra/Category/Ring/Limits.lean index a7f813b611915..a0c514581878e 100644 --- a/Mathlib/Algebra/Category/Ring/Limits.lean +++ b/Mathlib/Algebra/Category/Ring/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Ring.Pi import Mathlib.Algebra.Category.Ring.Basic diff --git a/Mathlib/Algebra/FreeAlgebra.lean b/Mathlib/Algebra/FreeAlgebra.lean index 9c27258acb6f9..e844d11c4c136 100644 --- a/Mathlib/Algebra/FreeAlgebra.lean +++ b/Mathlib/Algebra/FreeAlgebra.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Adam Topaz, Eric Wieser +Authors: Kim Morrison, Adam Topaz, Eric Wieser -/ import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Algebra.Tower diff --git a/Mathlib/Algebra/Group/Commute/Hom.lean b/Mathlib/Algebra/Group/Commute/Hom.lean index e4279c1534a47..f95402d1287eb 100644 --- a/Mathlib/Algebra/Group/Commute/Hom.lean +++ b/Mathlib/Algebra/Group/Commute/Hom.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Kevin Buzzard, Scott Morrison, Johan Commelin, Chris Hughes, +Authors: Patrick Massot, Kevin Buzzard, Kim Morrison, Johan Commelin, Chris Hughes, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Group.Commute.Defs diff --git a/Mathlib/Algebra/Group/Hom/Basic.lean b/Mathlib/Algebra/Group/Hom/Basic.lean index bac422e61797b..148098efacb87 100644 --- a/Mathlib/Algebra/Group/Hom/Basic.lean +++ b/Mathlib/Algebra/Group/Hom/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Kevin Buzzard, Scott Morrison, Johan Commelin, Chris Hughes, +Authors: Patrick Massot, Kevin Buzzard, Kim Morrison, Johan Commelin, Chris Hughes, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Group.Basic diff --git a/Mathlib/Algebra/Group/Hom/Defs.lean b/Mathlib/Algebra/Group/Hom/Defs.lean index 2b4249d02d413..f495bba039807 100644 --- a/Mathlib/Algebra/Group/Hom/Defs.lean +++ b/Mathlib/Algebra/Group/Hom/Defs.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Kevin Buzzard, Scott Morrison, Johan Commelin, Chris Hughes, +Authors: Patrick Massot, Kevin Buzzard, Kim Morrison, Johan Commelin, Chris Hughes, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Group.Pi.Basic diff --git a/Mathlib/Algebra/Group/Hom/End.lean b/Mathlib/Algebra/Group/Hom/End.lean index 207791e8b527c..00405f5550e0e 100644 --- a/Mathlib/Algebra/Group/Hom/End.lean +++ b/Mathlib/Algebra/Group/Hom/End.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Kevin Buzzard, Scott Morrison, Johan Commelin, Chris Hughes, +Authors: Patrick Massot, Kevin Buzzard, Kim Morrison, Johan Commelin, Chris Hughes, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Group.Commute.Defs diff --git a/Mathlib/Algebra/Group/Hom/Instances.lean b/Mathlib/Algebra/Group/Hom/Instances.lean index 3b1f5e56a0684..f3371cbd05280 100644 --- a/Mathlib/Algebra/Group/Hom/Instances.lean +++ b/Mathlib/Algebra/Group/Hom/Instances.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Kevin Buzzard, Scott Morrison, Johan Commelin, Chris Hughes, +Authors: Patrick Massot, Kevin Buzzard, Kim Morrison, Johan Commelin, Chris Hughes, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Group.Hom.Basic diff --git a/Mathlib/Algebra/Group/ULift.lean b/Mathlib/Algebra/Group/ULift.lean index 423ee6578ba6b..ce331c7da8288 100644 --- a/Mathlib/Algebra/Group/ULift.lean +++ b/Mathlib/Algebra/Group/ULift.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Algebra.Group.InjSurj diff --git a/Mathlib/Algebra/GroupWithZero/ULift.lean b/Mathlib/Algebra/GroupWithZero/ULift.lean index 2e370b30faa0a..f178a5b637230 100644 --- a/Mathlib/Algebra/GroupWithZero/ULift.lean +++ b/Mathlib/Algebra/GroupWithZero/ULift.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.ULift import Mathlib.Algebra.GroupWithZero.InjSurj diff --git a/Mathlib/Algebra/HierarchyDesign.lean b/Mathlib/Algebra/HierarchyDesign.lean index 862788ae48368..b2fe9b97fe510 100644 --- a/Mathlib/Algebra/HierarchyDesign.lean +++ b/Mathlib/Algebra/HierarchyDesign.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Eric Wieser +Authors: Kim Morrison, Eric Wieser -/ import Mathlib.Init import Batteries.Util.LibraryNote diff --git a/Mathlib/Algebra/Homology/Additive.lean b/Mathlib/Algebra/Homology/Additive.lean index b2988fbd4aba9..85979eabec627 100644 --- a/Mathlib/Algebra/Homology/Additive.lean +++ b/Mathlib/Algebra/Homology/Additive.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.Single import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor diff --git a/Mathlib/Algebra/Homology/Augment.lean b/Mathlib/Algebra/Homology/Augment.lean index 0b02a3d3140cd..c72e003fc7557 100644 --- a/Mathlib/Algebra/Homology/Augment.lean +++ b/Mathlib/Algebra/Homology/Augment.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.Single diff --git a/Mathlib/Algebra/Homology/ComplexShape.lean b/Mathlib/Algebra/Homology/ComplexShape.lean index e4da8ba92cfdf..2b46e9d743bc7 100644 --- a/Mathlib/Algebra/Homology/ComplexShape.lean +++ b/Mathlib/Algebra/Homology/ComplexShape.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison +Authors: Johan Commelin, Kim Morrison -/ import Mathlib.Algebra.Group.Defs import Mathlib.Logic.Relation diff --git a/Mathlib/Algebra/Homology/DifferentialObject.lean b/Mathlib/Algebra/Homology/DifferentialObject.lean index cd85f3f0e9e6c..d1b9484894419 100644 --- a/Mathlib/Algebra/Homology/DifferentialObject.lean +++ b/Mathlib/Algebra/Homology/DifferentialObject.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.HomologicalComplex import Mathlib.CategoryTheory.DifferentialObject diff --git a/Mathlib/Algebra/Homology/HomologicalBicomplex.lean b/Mathlib/Algebra/Homology/HomologicalBicomplex.lean index c693b7880842a..b02aad6a648b8 100644 --- a/Mathlib/Algebra/Homology/HomologicalBicomplex.lean +++ b/Mathlib/Algebra/Homology/HomologicalBicomplex.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou +Authors: Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Homology.HomologicalComplex diff --git a/Mathlib/Algebra/Homology/HomologicalComplex.lean b/Mathlib/Algebra/Homology/HomologicalComplex.lean index 59f2a43f6c5a1..2494b21c2eb58 100644 --- a/Mathlib/Algebra/Homology/HomologicalComplex.lean +++ b/Mathlib/Algebra/Homology/HomologicalComplex.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison +Authors: Johan Commelin, Kim Morrison -/ import Mathlib.Algebra.Homology.ComplexShape import Mathlib.CategoryTheory.Subobject.Limits diff --git a/Mathlib/Algebra/Homology/Homotopy.lean b/Mathlib/Algebra/Homology/Homotopy.lean index 4ee6bcba875ef..f8c43c0d2b844 100644 --- a/Mathlib/Algebra/Homology/Homotopy.lean +++ b/Mathlib/Algebra/Homology/Homotopy.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.Linear import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex diff --git a/Mathlib/Algebra/Homology/HomotopyCategory.lean b/Mathlib/Algebra/Homology/HomotopyCategory.lean index a938f482ae5ea..93400ddd35d94 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.Homotopy import Mathlib.Algebra.Homology.Linear diff --git a/Mathlib/Algebra/Homology/ImageToKernel.lean b/Mathlib/Algebra/Homology/ImageToKernel.lean index 0924d56092539..16f064b89a76f 100644 --- a/Mathlib/Algebra/Homology/ImageToKernel.lean +++ b/Mathlib/Algebra/Homology/ImageToKernel.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.Limits diff --git a/Mathlib/Algebra/Homology/LocalCohomology.lean b/Mathlib/Algebra/Homology/LocalCohomology.lean index 9680ba6f95b0e..4ea0bfce99d36 100644 --- a/Mathlib/Algebra/Homology/LocalCohomology.lean +++ b/Mathlib/Algebra/Homology/LocalCohomology.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Emily Witt. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Emily Witt, Scott Morrison, Jake Levinson, Sam van Gool +Authors: Emily Witt, Kim Morrison, Jake Levinson, Sam van Gool -/ import Mathlib.RingTheory.Ideal.Basic import Mathlib.Algebra.Category.ModuleCat.Colimits diff --git a/Mathlib/Algebra/Homology/QuasiIso.lean b/Mathlib/Algebra/Homology/QuasiIso.lean index dbb3e8cbd051b..47a65f02f7de3 100644 --- a/Mathlib/Algebra/Homology/QuasiIso.lean +++ b/Mathlib/Algebra/Homology/QuasiIso.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou +Authors: Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Homology.Homotopy diff --git a/Mathlib/Algebra/Homology/Single.lean b/Mathlib/Algebra/Homology/Single.lean index 833e8089b75d2..6adb409ebcd24 100644 --- a/Mathlib/Algebra/Homology/Single.lean +++ b/Mathlib/Algebra/Homology/Single.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.HomologicalComplex diff --git a/Mathlib/Algebra/Module/Algebra.lean b/Mathlib/Algebra/Module/Algebra.lean index d2cee9bce327b..6fb1b53849c2b 100644 --- a/Mathlib/Algebra/Module/Algebra.lean +++ b/Mathlib/Algebra/Module/Algebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Module.Defs import Mathlib.Algebra.Algebra.Basic diff --git a/Mathlib/Algebra/Module/ULift.lean b/Mathlib/Algebra/Module/ULift.lean index 730083e6948c9..1517ff6089728 100644 --- a/Mathlib/Algebra/Module/ULift.lean +++ b/Mathlib/Algebra/Module/ULift.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.GroupWithZero.ULift import Mathlib.Algebra.Ring.ULift diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index fbcb1227f5c8a..c859345b543ca 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johannes Hölzl, Yury Kudryashov, Scott Morrison +Authors: Johannes Hölzl, Yury Kudryashov, Kim Morrison -/ import Mathlib.Algebra.MonoidAlgebra.Defs import Mathlib.Algebra.Algebra.NonUnitalHom diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index bde744f6f77e4..f0273652c337c 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johannes Hölzl, Yury Kudryashov, Scott Morrison +Authors: Johannes Hölzl, Yury Kudryashov, Kim Morrison -/ import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.Module.BigOperators diff --git a/Mathlib/Algebra/MvPolynomial/Polynomial.lean b/Mathlib/Algebra/MvPolynomial/Polynomial.lean index f04fac634e9f1..529c8a050c772 100644 --- a/Mathlib/Algebra/MvPolynomial/Polynomial.lean +++ b/Mathlib/Algebra/MvPolynomial/Polynomial.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.MvPolynomial.Equiv import Mathlib.Algebra.Polynomial.Eval diff --git a/Mathlib/Algebra/Order/Algebra.lean b/Mathlib/Algebra/Order/Algebra.lean index 675c50fd0e04d..dc583079f431f 100644 --- a/Mathlib/Algebra/Order/Algebra.lean +++ b/Mathlib/Algebra/Order/Algebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Algebra.Defs import Mathlib.Algebra.Order.Module.OrderedSMul diff --git a/Mathlib/Algebra/Order/Group/Cone.lean b/Mathlib/Algebra/Order/Group/Cone.lean index 4cf5650b2afb0..a49307108ac8e 100644 --- a/Mathlib/Algebra/Order/Group/Cone.lean +++ b/Mathlib/Algebra/Order/Group/Cone.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Scott Morrison, Artie Khovanov +Authors: Mario Carneiro, Kim Morrison, Artie Khovanov -/ import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Monoid.Submonoid diff --git a/Mathlib/Algebra/Order/Interval/Set/Instances.lean b/Mathlib/Algebra/Order/Interval/Set/Instances.lean index ff54fbdebf8a3..74e41d229a3ff 100644 --- a/Mathlib/Algebra/Order/Interval/Set/Instances.lean +++ b/Mathlib/Algebra/Order/Interval/Set/Instances.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Stuart Presnell. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stuart Presnell, Eric Wieser, Yaël Dillies, Patrick Massot, Scott Morrison +Authors: Stuart Presnell, Eric Wieser, Yaël Dillies, Patrick Massot, Kim Morrison -/ import Mathlib.Algebra.Order.Ring.Basic import Mathlib.Algebra.Ring.Regular diff --git a/Mathlib/Algebra/Order/Star/Basic.lean b/Mathlib/Algebra/Order/Star/Basic.lean index 055ffe59379d4..b07145ac25911 100644 --- a/Mathlib/Algebra/Order/Star/Basic.lean +++ b/Mathlib/Algebra/Order/Star/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.Star.SelfAdjoint diff --git a/Mathlib/Algebra/Order/Sub/Prod.lean b/Mathlib/Algebra/Order/Sub/Prod.lean index de620a351ddd8..9dcb9c7e845d2 100644 --- a/Mathlib/Algebra/Order/Sub/Prod.lean +++ b/Mathlib/Algebra/Order/Sub/Prod.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Order.Sub.Defs diff --git a/Mathlib/Algebra/Polynomial/AlgebraMap.lean b/Mathlib/Algebra/Polynomial/AlgebraMap.lean index 1054f4209f86c..5928ff633fda6 100644 --- a/Mathlib/Algebra/Polynomial/AlgebraMap.lean +++ b/Mathlib/Algebra/Polynomial/AlgebraMap.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Algebra.Pi import Mathlib.Algebra.Polynomial.Eval diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index f82a2f6d2e2c3..b1d85a96da4bd 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Data.Finset.Sort diff --git a/Mathlib/Algebra/Polynomial/Coeff.lean b/Mathlib/Algebra/Polynomial/Coeff.lean index fe2f8eca5f560..a0550adae74d1 100644 --- a/Mathlib/Algebra/Polynomial/Coeff.lean +++ b/Mathlib/Algebra/Polynomial/Coeff.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.MonoidAlgebra.Support import Mathlib.Algebra.Polynomial.Basic diff --git a/Mathlib/Algebra/Polynomial/Degree/Definitions.lean b/Mathlib/Algebra/Polynomial/Degree/Definitions.lean index c1bc0023501f9..1d9ab3832d4fb 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Definitions.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Definitions.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.MonoidAlgebra.Degree import Mathlib.Algebra.Polynomial.Coeff diff --git a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean index d3cc2b29e0004..649bab3a13526 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Eval diff --git a/Mathlib/Algebra/Polynomial/Derivative.lean b/Mathlib/Algebra/Polynomial/Derivative.lean index d29f194ce5d73..b2767e3897214 100644 --- a/Mathlib/Algebra/Polynomial/Derivative.lean +++ b/Mathlib/Algebra/Polynomial/Derivative.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Algebra.Polynomial.Eval diff --git a/Mathlib/Algebra/Polynomial/Div.lean b/Mathlib/Algebra/Polynomial/Div.lean index 5dacd0350992a..7ac2f94a0beb8 100644 --- a/Mathlib/Algebra/Polynomial/Div.lean +++ b/Mathlib/Algebra/Polynomial/Div.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Inductions import Mathlib.Algebra.Polynomial.Monic diff --git a/Mathlib/Algebra/Polynomial/Eval.lean b/Mathlib/Algebra/Polynomial/Eval.lean index a84dbf87c705f..e6b4d34e657aa 100644 --- a/Mathlib/Algebra/Polynomial/Eval.lean +++ b/Mathlib/Algebra/Polynomial/Eval.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Degree.Definitions import Mathlib.Algebra.Polynomial.Induction diff --git a/Mathlib/Algebra/Polynomial/FieldDivision.lean b/Mathlib/Algebra/Polynomial/FieldDivision.lean index 0df84dde52989..8f5cad434faf7 100644 --- a/Mathlib/Algebra/Polynomial/FieldDivision.lean +++ b/Mathlib/Algebra/Polynomial/FieldDivision.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Derivative import Mathlib.Algebra.Polynomial.Roots diff --git a/Mathlib/Algebra/Polynomial/Identities.lean b/Mathlib/Algebra/Polynomial/Identities.lean index 03eec7652a472..d33dfaf9c2923 100644 --- a/Mathlib/Algebra/Polynomial/Identities.lean +++ b/Mathlib/Algebra/Polynomial/Identities.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Derivative import Mathlib.Tactic.LinearCombination diff --git a/Mathlib/Algebra/Polynomial/Induction.lean b/Mathlib/Algebra/Polynomial/Induction.lean index 242facc658dde..4ba0e2bf397db 100644 --- a/Mathlib/Algebra/Polynomial/Induction.lean +++ b/Mathlib/Algebra/Polynomial/Induction.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Basic import Mathlib.RingTheory.Ideal.Basic diff --git a/Mathlib/Algebra/Polynomial/Inductions.lean b/Mathlib/Algebra/Polynomial/Inductions.lean index f5a98d3c5ebe0..2594bd1490eca 100644 --- a/Mathlib/Algebra/Polynomial/Inductions.lean +++ b/Mathlib/Algebra/Polynomial/Inductions.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Damiano Testa, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Damiano Testa, Jens Wagemaker -/ import Mathlib.Algebra.MonoidAlgebra.Division import Mathlib.Algebra.Polynomial.Degree.Definitions diff --git a/Mathlib/Algebra/Polynomial/Monic.lean b/Mathlib/Algebra/Polynomial/Monic.lean index 9ab637bcebdd6..eb0f0cf67b6b0 100644 --- a/Mathlib/Algebra/Polynomial/Monic.lean +++ b/Mathlib/Algebra/Polynomial/Monic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Reverse import Mathlib.Algebra.Regular.SMul diff --git a/Mathlib/Algebra/Polynomial/Monomial.lean b/Mathlib/Algebra/Polynomial/Monomial.lean index e96bdc18024b0..29b15cda6f45e 100644 --- a/Mathlib/Algebra/Polynomial/Monomial.lean +++ b/Mathlib/Algebra/Polynomial/Monomial.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.Basic diff --git a/Mathlib/Algebra/Polynomial/RingDivision.lean b/Mathlib/Algebra/Polynomial/RingDivision.lean index e4e14ccf3d644..ab1ca1c76d94d 100644 --- a/Mathlib/Algebra/Polynomial/RingDivision.lean +++ b/Mathlib/Algebra/Polynomial/RingDivision.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker, Johan Commelin +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker, Johan Commelin -/ import Mathlib.Algebra.Polynomial.AlgebraMap import Mathlib.Algebra.Polynomial.BigOperators diff --git a/Mathlib/Algebra/Polynomial/Roots.lean b/Mathlib/Algebra/Polynomial/Roots.lean index 31ec3bba778f1..59f7f94c78993 100644 --- a/Mathlib/Algebra/Polynomial/Roots.lean +++ b/Mathlib/Algebra/Polynomial/Roots.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker, Johan Commelin +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker, Johan Commelin -/ import Mathlib.Algebra.Polynomial.RingDivision diff --git a/Mathlib/Algebra/Ring/ULift.lean b/Mathlib/Algebra/Ring/ULift.lean index d22da7ec4c22e..b0d8c9a46ca7d 100644 --- a/Mathlib/Algebra/Ring/ULift.lean +++ b/Mathlib/Algebra/Ring/ULift.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.ULift import Mathlib.Algebra.Ring.Equiv diff --git a/Mathlib/Algebra/RingQuot.lean b/Mathlib/Algebra/RingQuot.lean index 65dc7e05fcf81..1da65c2031d8e 100644 --- a/Mathlib/Algebra/RingQuot.lean +++ b/Mathlib/Algebra/RingQuot.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Algebra.Hom import Mathlib.RingTheory.Ideal.Quotient diff --git a/Mathlib/Algebra/Star/Basic.lean b/Mathlib/Algebra/Star/Basic.lean index 35276edb14891..99fd9d0f28098 100644 --- a/Mathlib/Algebra/Star/Basic.lean +++ b/Mathlib/Algebra/Star/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Field.Defs import Mathlib.Algebra.Group.Invertible.Defs diff --git a/Mathlib/Algebra/Star/CHSH.lean b/Mathlib/Algebra/Star/CHSH.lean index 6d92b8ca15050..26fc0b59288bb 100644 --- a/Mathlib/Algebra/Star/CHSH.lean +++ b/Mathlib/Algebra/Star/CHSH.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.CharP.Invertible import Mathlib.Algebra.Order.Star.Basic diff --git a/Mathlib/Algebra/Star/Subalgebra.lean b/Mathlib/Algebra/Star/Subalgebra.lean index b0dc2097f565e..7d0b23cd8f043 100644 --- a/Mathlib/Algebra/Star/Subalgebra.lean +++ b/Mathlib/Algebra/Star/Subalgebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Jireh Loreaux +Authors: Kim Morrison, Jireh Loreaux -/ import Mathlib.Algebra.Star.Center import Mathlib.Algebra.Star.StarAlgHom diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index fab17a4f32795..083a5943ef221 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.AlgebraicGeometry.Spec import Mathlib.Algebra.Category.Ring.Constructions diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index b60cff5c8de99..3a10a69127f49 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Justus Springer +Authors: Kim Morrison, Justus Springer -/ import Mathlib.Geometry.RingedSpace.LocallyRingedSpace import Mathlib.AlgebraicGeometry.StructureSheaf diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 692b54e2ecf76..6d18e0fcb5c9f 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison +Authors: Johan Commelin, Kim Morrison -/ import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic import Mathlib.Algebra.Category.Ring.Colimits diff --git a/Mathlib/AlgebraicTopology/MooreComplex.lean b/Mathlib/AlgebraicTopology/MooreComplex.lean index 62e4f9ca124ea..5ab0ded88a8b6 100644 --- a/Mathlib/AlgebraicTopology/MooreComplex.lean +++ b/Mathlib/AlgebraicTopology/MooreComplex.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Homology.HomologicalComplex import Mathlib.AlgebraicTopology.SimplicialObject diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index b041587897784..e72f2e8cd7bec 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison, Adam Topaz +Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.Tactic.Linarith import Mathlib.CategoryTheory.Skeletal diff --git a/Mathlib/AlgebraicTopology/SimplicialObject.lean b/Mathlib/AlgebraicTopology/SimplicialObject.lean index 4d65c1b5fcf57..ea02f63a11c95 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison, Adam Topaz +Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplexCategory import Mathlib.CategoryTheory.Comma.Arrow diff --git a/Mathlib/AlgebraicTopology/SimplicialSet.lean b/Mathlib/AlgebraicTopology/SimplicialSet.lean index e20ccf4e006ff..a8198f848a6c7 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison, Adam Topaz +Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplicialObject import Mathlib.CategoryTheory.Limits.Shapes.Types diff --git a/Mathlib/AlgebraicTopology/SingularSet.lean b/Mathlib/AlgebraicTopology/SingularSet.lean index 21364f30fc245..bc3d246833408 100644 --- a/Mathlib/AlgebraicTopology/SingularSet.lean +++ b/Mathlib/AlgebraicTopology/SingularSet.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison, Adam Topaz +Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplicialSet import Mathlib.AlgebraicTopology.TopologicalSimplex diff --git a/Mathlib/Analysis/Convex/Caratheodory.lean b/Mathlib/Analysis/Convex/Caratheodory.lean index 4d14dfff94413..5d81223dc517b 100644 --- a/Mathlib/Analysis/Convex/Caratheodory.lean +++ b/Mathlib/Analysis/Convex/Caratheodory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison +Authors: Johan Commelin, Kim Morrison -/ import Mathlib.Analysis.Convex.Combination import Mathlib.LinearAlgebra.AffineSpace.Independent diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean index 1f32d6b23b009..e5aff9ade9489 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Riccardo Brasca, Johan Commelin, Scott Morrison +Authors: Riccardo Brasca, Johan Commelin, Kim Morrison -/ import Mathlib.Analysis.Normed.Group.SemiNormedGrp import Mathlib.Analysis.Normed.Group.Quotient diff --git a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean index 0c75f3319bb3d..71515ffc2fc55 100644 --- a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean +++ b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.RingTheory.Polynomial.Bernstein diff --git a/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean b/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean index 6486b7bbab466..0d05481d7f037 100644 --- a/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean +++ b/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Analysis.Normed.Module.Dual import Mathlib.Analysis.Complex.Basic diff --git a/Mathlib/CategoryTheory/Abelian/Basic.lean b/Mathlib/CategoryTheory/Abelian/Basic.lean index b7e4dbcf98889..cc0db03e5a10b 100644 --- a/Mathlib/CategoryTheory/Abelian/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Johan Commelin, Scott Morrison +Authors: Markus Himmel, Johan Commelin, Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Constructions.Pullbacks import Mathlib.CategoryTheory.Preadditive.Biproducts diff --git a/Mathlib/CategoryTheory/Abelian/Ext.lean b/Mathlib/CategoryTheory/Abelian/Ext.lean index 63698a865b338..223c0b659b3b2 100644 --- a/Mathlib/CategoryTheory/Abelian/Ext.lean +++ b/Mathlib/CategoryTheory/Abelian/Ext.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Adam Topaz +Authors: Kim Morrison, Adam Topaz -/ import Mathlib.Algebra.Category.ModuleCat.Abelian import Mathlib.Algebra.Homology.Opposite diff --git a/Mathlib/CategoryTheory/Abelian/FunctorCategory.lean b/Mathlib/CategoryTheory/Abelian/FunctorCategory.lean index b3b746622ceed..8178bfae61ecf 100644 --- a/Mathlib/CategoryTheory/Abelian/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Abelian/FunctorCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Abelian.Basic import Mathlib.CategoryTheory.Preadditive.FunctorCategory diff --git a/Mathlib/CategoryTheory/Abelian/Images.lean b/Mathlib/CategoryTheory/Abelian/Images.lean index 58a0dcda3e32b..c753cc0c81887 100644 --- a/Mathlib/CategoryTheory/Abelian/Images.lean +++ b/Mathlib/CategoryTheory/Abelian/Images.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.Kernels diff --git a/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean b/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean index a7565550d51fd..675ab43cfcce7 100644 --- a/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jujian Zhang, Scott Morrison +Authors: Jujian Zhang, Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.InjectiveResolution import Mathlib.Algebra.Homology.HomotopyCategory diff --git a/Mathlib/CategoryTheory/Abelian/LeftDerived.lean b/Mathlib/CategoryTheory/Abelian/LeftDerived.lean index be9b3ab46d0c2..f9333349b110b 100644 --- a/Mathlib/CategoryTheory/Abelian/LeftDerived.lean +++ b/Mathlib/CategoryTheory/Abelian/LeftDerived.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Riccardo Brasca, Adam Topaz, Jujian Zhang, Joël Riou +Authors: Kim Morrison, Riccardo Brasca, Adam Topaz, Jujian Zhang, Joël Riou -/ import Mathlib.Algebra.Homology.Additive import Mathlib.CategoryTheory.Abelian.ProjectiveResolution diff --git a/Mathlib/CategoryTheory/Abelian/Opposite.lean b/Mathlib/CategoryTheory/Abelian/Opposite.lean index 6c2747ade568d..e862e8a81c331 100644 --- a/Mathlib/CategoryTheory/Abelian/Opposite.lean +++ b/Mathlib/CategoryTheory/Abelian/Opposite.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Abelian.Basic import Mathlib.CategoryTheory.Preadditive.Opposite diff --git a/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean b/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean index 854dacb44ab3e..b46ed6087d1b3 100644 --- a/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison, Jakob von Raumer, Joël Riou +Authors: Markus Himmel, Kim Morrison, Jakob von Raumer, Joël Riou -/ import Mathlib.CategoryTheory.Preadditive.ProjectiveResolution import Mathlib.Algebra.Homology.HomotopyCategory diff --git a/Mathlib/CategoryTheory/Abelian/RightDerived.lean b/Mathlib/CategoryTheory/Abelian/RightDerived.lean index 2c12f1e56530f..8cf24315d8930 100644 --- a/Mathlib/CategoryTheory/Abelian/RightDerived.lean +++ b/Mathlib/CategoryTheory/Abelian/RightDerived.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jujian Zhang, Scott Morrison, Joël Riou +Authors: Jujian Zhang, Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Homology.Additive import Mathlib.CategoryTheory.Abelian.InjectiveResolution diff --git a/Mathlib/CategoryTheory/Abelian/Transfer.lean b/Mathlib/CategoryTheory/Abelian/Transfer.lean index 9e05999b3184a..5a3c93413c248 100644 --- a/Mathlib/CategoryTheory/Abelian/Transfer.lean +++ b/Mathlib/CategoryTheory/Abelian/Transfer.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Abelian.Basic import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Kernels diff --git a/Mathlib/CategoryTheory/Adjunction/FullyFaithful.lean b/Mathlib/CategoryTheory/Adjunction/FullyFaithful.lean index c1e9ac499f5a3..2bdec90917b38 100644 --- a/Mathlib/CategoryTheory/Adjunction/FullyFaithful.lean +++ b/Mathlib/CategoryTheory/Adjunction/FullyFaithful.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Dagur Asgeirsson +Authors: Kim Morrison, Dagur Asgeirsson -/ import Mathlib.CategoryTheory.Adjunction.Basic import Mathlib.CategoryTheory.MorphismProperty.Basic diff --git a/Mathlib/CategoryTheory/Adjunction/Restrict.lean b/Mathlib/CategoryTheory/Adjunction/Restrict.lean index ace8874876429..d3e8258ab5062 100644 --- a/Mathlib/CategoryTheory/Adjunction/Restrict.lean +++ b/Mathlib/CategoryTheory/Adjunction/Restrict.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Adjunction.Basic import Mathlib.CategoryTheory.HomCongr diff --git a/Mathlib/CategoryTheory/Bicategory/End.lean b/Mathlib/CategoryTheory/Bicategory/End.lean index 1caa7d9c14e97..8210d2a2cdcd0 100644 --- a/Mathlib/CategoryTheory/Bicategory/End.lean +++ b/Mathlib/CategoryTheory/Bicategory/End.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Bicategory.Basic import Mathlib.CategoryTheory.Monoidal.Category diff --git a/Mathlib/CategoryTheory/Bicategory/SingleObj.lean b/Mathlib/CategoryTheory/Bicategory/SingleObj.lean index 7619fce58c22c..73341c73d8e16 100644 --- a/Mathlib/CategoryTheory/Bicategory/SingleObj.lean +++ b/Mathlib/CategoryTheory/Bicategory/SingleObj.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Bicategory.End import Mathlib.CategoryTheory.Monoidal.Functor diff --git a/Mathlib/CategoryTheory/Category/Basic.lean b/Mathlib/CategoryTheory/Category/Basic.lean index 7ee03f2c7df53..d314808670795 100644 --- a/Mathlib/CategoryTheory/Category/Basic.lean +++ b/Mathlib/CategoryTheory/Category/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison, Johannes Hölzl, Reid Barton +Authors: Stephen Morgan, Kim Morrison, Johannes Hölzl, Reid Barton -/ import Mathlib.CategoryTheory.Category.Init import Mathlib.Combinatorics.Quiver.Basic diff --git a/Mathlib/CategoryTheory/Category/Cat/Limit.lean b/Mathlib/CategoryTheory/Category/Cat/Limit.lean index 6b3e9d578c572..8fb276edac4be 100644 --- a/Mathlib/CategoryTheory/Category/Cat/Limit.lean +++ b/Mathlib/CategoryTheory/Category/Cat/Limit.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Category.Cat import Mathlib.CategoryTheory.Limits.Types diff --git a/Mathlib/CategoryTheory/Category/GaloisConnection.lean b/Mathlib/CategoryTheory/Category/GaloisConnection.lean index 41362d5292353..a79e29a39e4c2 100644 --- a/Mathlib/CategoryTheory/Category/GaloisConnection.lean +++ b/Mathlib/CategoryTheory/Category/GaloisConnection.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison, Johannes Hölzl, Reid Barton +Authors: Stephen Morgan, Kim Morrison, Johannes Hölzl, Reid Barton -/ import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.Adjunction.Basic diff --git a/Mathlib/CategoryTheory/Category/Pairwise.lean b/Mathlib/CategoryTheory/Category/Pairwise.lean index a8e795bdc19ac..7b800d357beb0 100644 --- a/Mathlib/CategoryTheory/Category/Pairwise.lean +++ b/Mathlib/CategoryTheory/Category/Pairwise.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Order.CompleteLattice import Mathlib.CategoryTheory.Category.Preorder diff --git a/Mathlib/CategoryTheory/Category/Preorder.lean b/Mathlib/CategoryTheory/Category/Preorder.lean index f46afa90197a5..f2935460a2529 100644 --- a/Mathlib/CategoryTheory/Category/Preorder.lean +++ b/Mathlib/CategoryTheory/Category/Preorder.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison, Johannes Hölzl, Reid Barton +Authors: Stephen Morgan, Kim Morrison, Johannes Hölzl, Reid Barton -/ import Mathlib.CategoryTheory.Equivalence import Mathlib.CategoryTheory.EqToHom diff --git a/Mathlib/CategoryTheory/Category/Quiv.lean b/Mathlib/CategoryTheory/Category/Quiv.lean index 40f840da97067..bdb427995bad6 100644 --- a/Mathlib/CategoryTheory/Category/Quiv.lean +++ b/Mathlib/CategoryTheory/Category/Quiv.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Adjunction.Basic import Mathlib.CategoryTheory.Category.Cat diff --git a/Mathlib/CategoryTheory/Category/RelCat.lean b/Mathlib/CategoryTheory/Category/RelCat.lean index 48f8c610da96b..7136d606db093 100644 --- a/Mathlib/CategoryTheory/Category/RelCat.lean +++ b/Mathlib/CategoryTheory/Category/RelCat.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Uni Marx +Authors: Kim Morrison, Uni Marx -/ import Mathlib.CategoryTheory.Iso import Mathlib.CategoryTheory.EssentialImage diff --git a/Mathlib/CategoryTheory/Closed/Monoidal.lean b/Mathlib/CategoryTheory/Closed/Monoidal.lean index 5a32bc0ce83e8..8309157796ab1 100644 --- a/Mathlib/CategoryTheory/Closed/Monoidal.lean +++ b/Mathlib/CategoryTheory/Closed/Monoidal.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Monoidal.Functor import Mathlib.CategoryTheory.Adjunction.Limits diff --git a/Mathlib/CategoryTheory/CommSq.lean b/Mathlib/CategoryTheory/CommSq.lean index ecb323faed1c4..f40df65859a4d 100644 --- a/Mathlib/CategoryTheory/CommSq.lean +++ b/Mathlib/CategoryTheory/CommSq.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou +Authors: Kim Morrison, Joël Riou -/ import Mathlib.CategoryTheory.Comma.Arrow diff --git a/Mathlib/CategoryTheory/Comma/Basic.lean b/Mathlib/CategoryTheory/Comma/Basic.lean index 892745edf3a95..c88e7997a1eeb 100644 --- a/Mathlib/CategoryTheory/Comma/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johan Commelin, Bhavik Mehta +Authors: Kim Morrison, Johan Commelin, Bhavik Mehta -/ import Mathlib.CategoryTheory.Iso import Mathlib.CategoryTheory.Functor.Category diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow.lean index 12b710e29af5b..3ee2b719536a8 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Adam Topaz, Scott Morrison +Authors: Adam Topaz, Kim Morrison -/ import Mathlib.CategoryTheory.Comma.Basic import Mathlib.CategoryTheory.PUnit diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 8ee159d8afb77..0e42d549b245a 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johannes Hölzl, Reid Barton, Sean Leather, Yury Kudryashov +Authors: Kim Morrison, Johannes Hölzl, Reid Barton, Sean Leather, Yury Kudryashov -/ import Mathlib.CategoryTheory.Types diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean index 365a1c9c6a877..d2a6dab1aa44a 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johannes Hölzl, Reid Barton, Sean Leather +Authors: Kim Morrison, Johannes Hölzl, Reid Barton, Sean Leather -/ import Mathlib.Init import Batteries.Tactic.Lint.Misc diff --git a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean index 201557ff6bf23..7293c742fab92 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Yury Kudryashov +Authors: Kim Morrison, Yury Kudryashov -/ import Mathlib.CategoryTheory.ConcreteCategory.Basic import Mathlib.CategoryTheory.ConcreteCategory.Bundled diff --git a/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean b/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean index 4bd471e67da9a..69e90e646f526 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.ConcreteCategory.Basic import Mathlib.CategoryTheory.Functor.ReflectsIso diff --git a/Mathlib/CategoryTheory/Core.lean b/Mathlib/CategoryTheory/Core.lean index e124cbff9a5bc..e7b1e69ea7ddc 100644 --- a/Mathlib/CategoryTheory/Core.lean +++ b/Mathlib/CategoryTheory/Core.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Control.EquivFunctor import Mathlib.CategoryTheory.Groupoid diff --git a/Mathlib/CategoryTheory/DifferentialObject.lean b/Mathlib/CategoryTheory/DifferentialObject.lean index 324755f59b43d..b5463218d54bf 100644 --- a/Mathlib/CategoryTheory/DifferentialObject.lean +++ b/Mathlib/CategoryTheory/DifferentialObject.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Basic import Mathlib.Data.Int.Cast.Defs diff --git a/Mathlib/CategoryTheory/DiscreteCategory.lean b/Mathlib/CategoryTheory/DiscreteCategory.lean index 3c5a2e2c0acd1..59798018c9623 100644 --- a/Mathlib/CategoryTheory/DiscreteCategory.lean +++ b/Mathlib/CategoryTheory/DiscreteCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Pi.Basic diff --git a/Mathlib/CategoryTheory/Elements.lean b/Mathlib/CategoryTheory/Elements.lean index d5fda0bbb9e35..3269eddc6bd86 100644 --- a/Mathlib/CategoryTheory/Elements.lean +++ b/Mathlib/CategoryTheory/Elements.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Comma.StructuredArrow import Mathlib.CategoryTheory.Groupoid diff --git a/Mathlib/CategoryTheory/Elementwise.lean b/Mathlib/CategoryTheory/Elementwise.lean index 3619c79b713f1..06fe4ef41ec18 100644 --- a/Mathlib/CategoryTheory/Elementwise.lean +++ b/Mathlib/CategoryTheory/Elementwise.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Tactic.CategoryTheory.Elementwise import Mathlib.CategoryTheory.ConcreteCategory.Basic diff --git a/Mathlib/CategoryTheory/Endofunctor/Algebra.lean b/Mathlib/CategoryTheory/Endofunctor/Algebra.lean index 0ba3c1ced4604..59d61ad43c4c1 100644 --- a/Mathlib/CategoryTheory/Endofunctor/Algebra.lean +++ b/Mathlib/CategoryTheory/Endofunctor/Algebra.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Joseph Hua. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta, Johan Commelin, Reid Barton, Robert Y. Lewis, Joseph Hua +Authors: Kim Morrison, Bhavik Mehta, Johan Commelin, Reid Barton, Robert Y. Lewis, Joseph Hua -/ import Mathlib.CategoryTheory.Limits.Shapes.Terminal diff --git a/Mathlib/CategoryTheory/Endomorphism.lean b/Mathlib/CategoryTheory/Endomorphism.lean index 30f789b4ad257..93109c730da29 100644 --- a/Mathlib/CategoryTheory/Endomorphism.lean +++ b/Mathlib/CategoryTheory/Endomorphism.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yury Kudryashov, Scott Morrison, Simon Hudon +Authors: Yury Kudryashov, Kim Morrison, Simon Hudon -/ import Mathlib.Algebra.Group.Action.Defs import Mathlib.Algebra.Group.Equiv.Basic diff --git a/Mathlib/CategoryTheory/Enriched/Basic.lean b/Mathlib/CategoryTheory/Enriched/Basic.lean index 325790ef8b742..f8f9518c24feb 100644 --- a/Mathlib/CategoryTheory/Enriched/Basic.lean +++ b/Mathlib/CategoryTheory/Enriched/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Types.Symmetric import Mathlib.CategoryTheory.Monoidal.Types.Coyoneda diff --git a/Mathlib/CategoryTheory/EpiMono.lean b/Mathlib/CategoryTheory/EpiMono.lean index a9cd25cb109d7..13cfd3e4ad1b3 100644 --- a/Mathlib/CategoryTheory/EpiMono.lean +++ b/Mathlib/CategoryTheory/EpiMono.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Scott Morrison +Authors: Reid Barton, Kim Morrison -/ import Mathlib.CategoryTheory.Opposites import Mathlib.CategoryTheory.Groupoid diff --git a/Mathlib/CategoryTheory/EqToHom.lean b/Mathlib/CategoryTheory/EqToHom.lean index b9a92d8d2782b..1a0622b180b50 100644 --- a/Mathlib/CategoryTheory/EqToHom.lean +++ b/Mathlib/CategoryTheory/EqToHom.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Scott Morrison +Authors: Reid Barton, Kim Morrison -/ import Mathlib.CategoryTheory.Opposites diff --git a/Mathlib/CategoryTheory/Equivalence.lean b/Mathlib/CategoryTheory/Equivalence.lean index 6e8a5e55a7204..0f2676be1e1e8 100644 --- a/Mathlib/CategoryTheory/Equivalence.lean +++ b/Mathlib/CategoryTheory/Equivalence.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Tim Baumann, Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Tim Baumann, Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.Functor.FullyFaithful import Mathlib.CategoryTheory.FullSubcategory diff --git a/Mathlib/CategoryTheory/EssentiallySmall.lean b/Mathlib/CategoryTheory/EssentiallySmall.lean index 88de842c58417..d3d3eb2c323fb 100644 --- a/Mathlib/CategoryTheory/EssentiallySmall.lean +++ b/Mathlib/CategoryTheory/EssentiallySmall.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Category.ULift import Mathlib.CategoryTheory.Skeletal diff --git a/Mathlib/CategoryTheory/Filtered/Basic.lean b/Mathlib/CategoryTheory/Filtered/Basic.lean index 5a95c5a14a315..688a1d9ce43a8 100644 --- a/Mathlib/CategoryTheory/Filtered/Basic.lean +++ b/Mathlib/CategoryTheory/Filtered/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Scott Morrison +Authors: Reid Barton, Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits diff --git a/Mathlib/CategoryTheory/FinCategory/AsType.lean b/Mathlib/CategoryTheory/FinCategory/AsType.lean index 9d42330a17b22..1ba7c2d3cd220 100644 --- a/Mathlib/CategoryTheory/FinCategory/AsType.lean +++ b/Mathlib/CategoryTheory/FinCategory/AsType.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Fintype.Card import Mathlib.CategoryTheory.FinCategory.Basic diff --git a/Mathlib/CategoryTheory/FinCategory/Basic.lean b/Mathlib/CategoryTheory/FinCategory/Basic.lean index 4ae9b8ca21320..294cc5a1a352f 100644 --- a/Mathlib/CategoryTheory/FinCategory/Basic.lean +++ b/Mathlib/CategoryTheory/FinCategory/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Fintype.Basic import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/FullSubcategory.lean b/Mathlib/CategoryTheory/FullSubcategory.lean index 8aa58d273b2d2..bf98131940b9e 100644 --- a/Mathlib/CategoryTheory/FullSubcategory.lean +++ b/Mathlib/CategoryTheory/FullSubcategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Reid Barton +Authors: Kim Morrison, Reid Barton -/ import Mathlib.CategoryTheory.Functor.FullyFaithful diff --git a/Mathlib/CategoryTheory/Functor/Basic.lean b/Mathlib/CategoryTheory/Functor/Basic.lean index bff78cc031a50..4be276945c1e4 100644 --- a/Mathlib/CategoryTheory/Functor/Basic.lean +++ b/Mathlib/CategoryTheory/Functor/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Tim Baumann, Stephen Morgan, Scott Morrison +Authors: Tim Baumann, Stephen Morgan, Kim Morrison -/ import Mathlib.CategoryTheory.Category.Basic diff --git a/Mathlib/CategoryTheory/Functor/Category.lean b/Mathlib/CategoryTheory/Functor/Category.lean index 654f3f72d8875..e1f0445ab692b 100644 --- a/Mathlib/CategoryTheory/Functor/Category.lean +++ b/Mathlib/CategoryTheory/Functor/Category.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Tim Baumann, Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Tim Baumann, Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.NatTrans import Mathlib.CategoryTheory.Iso diff --git a/Mathlib/CategoryTheory/Functor/Const.lean b/Mathlib/CategoryTheory/Functor/Const.lean index 006504deb58b6..5c783b8742f00 100644 --- a/Mathlib/CategoryTheory/Functor/Const.lean +++ b/Mathlib/CategoryTheory/Functor/Const.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Opposites diff --git a/Mathlib/CategoryTheory/Functor/Currying.lean b/Mathlib/CategoryTheory/Functor/Currying.lean index caa5be9b7f6d8..edaba6e369347 100644 --- a/Mathlib/CategoryTheory/Functor/Currying.lean +++ b/Mathlib/CategoryTheory/Functor/Currying.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean index cbc95c08b955f..82f3de969be51 100644 --- a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean +++ b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.NatIso import Mathlib.Logic.Equiv.Defs diff --git a/Mathlib/CategoryTheory/Functor/Functorial.lean b/Mathlib/CategoryTheory/Functor/Functorial.lean index 7b9fadaad4f11..f55993471df00 100644 --- a/Mathlib/CategoryTheory/Functor/Functorial.lean +++ b/Mathlib/CategoryTheory/Functor/Functorial.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Functor.Basic diff --git a/Mathlib/CategoryTheory/Functor/Hom.lean b/Mathlib/CategoryTheory/Functor/Hom.lean index 01f3ac9dd321f..225924cf02b07 100644 --- a/Mathlib/CategoryTheory/Functor/Hom.lean +++ b/Mathlib/CategoryTheory/Functor/Hom.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Scott Morrison +Authors: Reid Barton, Kim Morrison -/ import Mathlib.CategoryTheory.Products.Basic import Mathlib.CategoryTheory.Types diff --git a/Mathlib/CategoryTheory/GradedObject.lean b/Mathlib/CategoryTheory/GradedObject.lean index fcee74c33d22f..c3fd1e2c4e0aa 100644 --- a/Mathlib/CategoryTheory/GradedObject.lean +++ b/Mathlib/CategoryTheory/GradedObject.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou +Authors: Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Group.Int import Mathlib.CategoryTheory.ConcreteCategory.Basic diff --git a/Mathlib/CategoryTheory/Grothendieck.lean b/Mathlib/CategoryTheory/Grothendieck.lean index 60f2b56671b81..59e0d242c7d00 100644 --- a/Mathlib/CategoryTheory/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Grothendieck.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Sina Hazratpour +Authors: Kim Morrison, Sina Hazratpour -/ import Mathlib.CategoryTheory.Category.Cat import Mathlib.CategoryTheory.Elements diff --git a/Mathlib/CategoryTheory/Groupoid.lean b/Mathlib/CategoryTheory/Groupoid.lean index 7bf9c52f3bc73..4799bc3879317 100644 --- a/Mathlib/CategoryTheory/Groupoid.lean +++ b/Mathlib/CategoryTheory/Groupoid.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Scott Morrison, David Wärn +Authors: Reid Barton, Kim Morrison, David Wärn -/ import Mathlib.CategoryTheory.FullSubcategory import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean index bd24ff1c503c6..8d7ad6c8ea53a 100644 --- a/Mathlib/CategoryTheory/Iso.lean +++ b/Mathlib/CategoryTheory/Iso.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Tim Baumann, Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Tim Baumann, Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.Tactic.CategoryTheory.Reassoc diff --git a/Mathlib/CategoryTheory/Limits/ColimitLimit.lean b/Mathlib/CategoryTheory/Limits/ColimitLimit.lean index 2628945db2029..23386c1aed4c1 100644 --- a/Mathlib/CategoryTheory/Limits/ColimitLimit.lean +++ b/Mathlib/CategoryTheory/Limits/ColimitLimit.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Types import Mathlib.CategoryTheory.Functor.Currying diff --git a/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean index 18cd6a039d479..48a15f47a5ca7 100644 --- a/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Adam Topaz +Authors: Kim Morrison, Adam Topaz -/ import Mathlib.CategoryTheory.ConcreteCategory.Basic import Mathlib.CategoryTheory.Limits.Preserves.Basic diff --git a/Mathlib/CategoryTheory/Limits/Cones.lean b/Mathlib/CategoryTheory/Limits/Cones.lean index 84e7ebc84d72c..157d042f4667c 100644 --- a/Mathlib/CategoryTheory/Limits/Cones.lean +++ b/Mathlib/CategoryTheory/Limits/Cones.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.Functor.Const import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean b/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean index b24dfdd50ae94..5cf6eebed9923 100644 --- a/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Bhavik Mehta, Scott Morrison +Authors: Bhavik Mehta, Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Constructions.BinaryProducts import Mathlib.CategoryTheory.Limits.Constructions.Equalizers diff --git a/Mathlib/CategoryTheory/Limits/Constructions/ZeroObjects.lean b/Mathlib/CategoryTheory/Limits/Constructions/ZeroObjects.lean index c67246dbd4d34..d978a5c54dda2 100644 --- a/Mathlib/CategoryTheory/Limits/Constructions/ZeroObjects.lean +++ b/Mathlib/CategoryTheory/Limits/Constructions/ZeroObjects.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.ZeroMorphisms import Mathlib.CategoryTheory.Limits.Constructions.BinaryProducts diff --git a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean index ffb3e847a42f9..70ea3b65e93a5 100644 --- a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean +++ b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.ColimitLimit import Mathlib.CategoryTheory.Limits.Preserves.FunctorCategory diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index 35224de3361f4..64975ca699d17 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Comma.StructuredArrow import Mathlib.CategoryTheory.IsConnected diff --git a/Mathlib/CategoryTheory/Limits/Fubini.lean b/Mathlib/CategoryTheory/Limits/Fubini.lean index 3bd7d06ef9472..898d073faa5a4 100644 --- a/Mathlib/CategoryTheory/Limits/Fubini.lean +++ b/Mathlib/CategoryTheory/Limits/Fubini.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.HasLimits import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean index b212bc76981ba..305a3bbd5a648 100644 --- a/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Functor.Currying import Mathlib.CategoryTheory.Limits.Preserves.Limits diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index fb9cbc923b3fc..5478f806f7e4b 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Mario Carneiro, Scott Morrison, Floris van Doorn +Authors: Reid Barton, Mario Carneiro, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.Limits.IsLimit import Mathlib.CategoryTheory.Category.ULift diff --git a/Mathlib/CategoryTheory/Limits/IsLimit.lean b/Mathlib/CategoryTheory/Limits/IsLimit.lean index ff385b709488f..76802822f383d 100644 --- a/Mathlib/CategoryTheory/Limits/IsLimit.lean +++ b/Mathlib/CategoryTheory/Limits/IsLimit.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Mario Carneiro, Scott Morrison, Floris van Doorn +Authors: Reid Barton, Mario Carneiro, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.Adjunction.Basic import Mathlib.CategoryTheory.Limits.Cones diff --git a/Mathlib/CategoryTheory/Limits/Lattice.lean b/Mathlib/CategoryTheory/Limits/Lattice.lean index 882daf68cd30e..ccf7e6cf11624 100644 --- a/Mathlib/CategoryTheory/Limits/Lattice.lean +++ b/Mathlib/CategoryTheory/Limits/Lattice.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Justus Springer +Authors: Kim Morrison, Justus Springer -/ import Mathlib.Order.CompleteLattice import Mathlib.Data.Finset.Lattice diff --git a/Mathlib/CategoryTheory/Limits/Opposites.lean b/Mathlib/CategoryTheory/Limits/Opposites.lean index 55f267f9bdae5..a988e6bc1335d 100644 --- a/Mathlib/CategoryTheory/Limits/Opposites.lean +++ b/Mathlib/CategoryTheory/Limits/Opposites.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Floris van Doorn +Authors: Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.Limits.Filtered import Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts diff --git a/Mathlib/CategoryTheory/Limits/Pi.lean b/Mathlib/CategoryTheory/Limits/Pi.lean index 605261fd6d113..eb68356542cfc 100644 --- a/Mathlib/CategoryTheory/Limits/Pi.lean +++ b/Mathlib/CategoryTheory/Limits/Pi.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Pi.Basic import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean b/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean index 803fcd12b6cc8..0926bbae01d71 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Reid Barton, Bhavik Mehta, Jakob von Raumer +Authors: Kim Morrison, Reid Barton, Bhavik Mehta, Jakob von Raumer -/ import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Filtered.lean b/Mathlib/CategoryTheory/Limits/Preserves/Filtered.lean index 1eb21050d5910..932826e7f60e0 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Filtered.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Filtered.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Justus Springer +Authors: Kim Morrison, Justus Springer -/ import Mathlib.CategoryTheory.Limits.Preserves.Basic import Mathlib.CategoryTheory.Filtered.Basic diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean b/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean index ad85619badaad..37599d523f5f6 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.Preserves.Basic diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean index 9a602e80dbec1..b6333a08c0d86 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.Kernels import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Zero diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Products.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Products.lean index 4d54f0f91c9b6..9d1105f497bd6 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Products.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Products.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison, Bhavik Mehta. All rights reserved. +Copyright (c) 2020 Kim Morrison, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.Shapes.Products import Mathlib.CategoryTheory.Limits.Preserves.Basic diff --git a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean index 160d8386ff9bc..4ea865a6b1d0d 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Comma.Over import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean index a079c16da2b22..dbb941df4e33f 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Jakob von Raumer +Authors: Kim Morrison, Jakob von Raumer -/ import Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean index d1f39b75f730a..3388588964ed5 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Joël Riou, Scott Morrison, Adam Topaz +Authors: Joël Riou, Kim Morrison, Adam Topaz -/ import Mathlib.CategoryTheory.Limits.Preserves.Shapes.BinaryProducts import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Products diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean index 499e8ff5ad36b..05a92677fd909 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Markus Himmel +Authors: Kim Morrison, Markus Himmel -/ import Mathlib.CategoryTheory.EpiMono import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean b/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean index 9cb33fc51bcc3..812d28171a0d8 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.FinCategory.AsType import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts diff --git a/Mathlib/CategoryTheory/Limits/Shapes/FiniteProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/FiniteProducts.lean index a8fc25c47121c..76f92fb28042f 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/FiniteProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/FiniteProducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits import Mathlib.CategoryTheory.Limits.Shapes.Products diff --git a/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean b/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean index 113f2c55cc2c3..0303e8d18d601 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean index 79301f40a8edc..22aa87a4a18cd 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Markus Himmel +Authors: Kim Morrison, Markus Himmel -/ import Mathlib.CategoryTheory.Limits.Shapes.Equalizers import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean index ec4bee1404520..c05a2ec92eaab 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Markus Himmel +Authors: Kim Morrison, Markus Himmel -/ import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Zero diff --git a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean index 93dfec509e2d4..e16617bd21fec 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.Shapes.RegularMono import Mathlib.CategoryTheory.Limits.Shapes.Kernels diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean index a614b5d85405d..e0595886fe9d9 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.HasLimits import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Assoc.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Assoc.lean index b6008f36b9768..541f09bc26155 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Assoc.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Assoc.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean index 665866bf2883a..e22ae9d2d8bed 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou, Calle Sönne +Authors: Kim Morrison, Joël Riou, Calle Sönne -/ import Mathlib.CategoryTheory.CommSq import Mathlib.CategoryTheory.Limits.Opposites diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Cospan.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Cospan.lean index dbd52eb783c0c..03f0894ee74ee 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Cospan.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Cospan.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Markus Himmel, Bhavik Mehta +Authors: Kim Morrison, Markus Himmel, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.Shapes.WidePullbacks import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean index d832ed2573d16..f6455c517bc0b 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Markus Himmel, Bhavik Mehta, Andrew Yang, Emily Riehl, Calle Sönne +Authors: Kim Morrison, Markus Himmel, Bhavik Mehta, Andrew Yang, Emily Riehl, Calle Sönne -/ import Mathlib.CategoryTheory.Limits.Shapes.Pullback.PullbackCone diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Iso.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Iso.lean index 0aec735dd25af..3007f243e923c 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Iso.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Iso.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean index 87a404f00fcb9..5393b03bb61a3 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta, Andrew Yang -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean index ddf8657ecc188..6790398f308af 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang, Calle Sönne -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean index 5c57de436f965..0c26846165918 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Markus Himmel, Bhavik Mehta, Andrew Yang, Emily Riehl, Calle Sönne +Authors: Kim Morrison, Markus Himmel, Bhavik Mehta, Andrew Yang, Emily Riehl, Calle Sönne -/ import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Cospan diff --git a/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean b/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean index 36ef641c0374a..c568df46e30c4 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.Shapes.Pullback.HasPullback import Mathlib.CategoryTheory.Limits.Shapes.StrongEpi diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Terminal.lean b/Mathlib/CategoryTheory/Limits/Shapes/Terminal.lean index c9f8914c57de7..37a4e622da924 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Terminal.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Terminal.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.PEmpty import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean index 7718d1bc251fd..5f9021a6e2f50 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Types import Mathlib.CategoryTheory.Limits.Shapes.Products diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean index 6aa46f0c5a128..259375ddca69a 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Pi.Basic import Mathlib.CategoryTheory.Limits.Shapes.Products diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean b/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean index d6dd788599bbf..54f3a9e56b996 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johan Commelin +Authors: Kim Morrison, Johan Commelin -/ import Mathlib.CategoryTheory.Limits.Shapes.Terminal diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index a5e6378568b97..cfa274313257e 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Reid Barton +Authors: Kim Morrison, Reid Barton -/ import Mathlib.Data.TypeMax import Mathlib.Logic.UnivLE diff --git a/Mathlib/CategoryTheory/Limits/TypesFiltered.lean b/Mathlib/CategoryTheory/Limits/TypesFiltered.lean index 3a9fd3a30e941..05dec6451b29c 100644 --- a/Mathlib/CategoryTheory/Limits/TypesFiltered.lean +++ b/Mathlib/CategoryTheory/Limits/TypesFiltered.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Reid Barton +Authors: Kim Morrison, Reid Barton -/ import Mathlib.CategoryTheory.Limits.Types import Mathlib.CategoryTheory.Filtered.Basic diff --git a/Mathlib/CategoryTheory/Limits/Unit.lean b/Mathlib/CategoryTheory/Limits/Unit.lean index 7b572e4455d15..21e52a45493b7 100644 --- a/Mathlib/CategoryTheory/Limits/Unit.lean +++ b/Mathlib/CategoryTheory/Limits/Unit.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.PUnit import Mathlib.CategoryTheory.Limits.HasLimits diff --git a/Mathlib/CategoryTheory/Limits/Yoneda.lean b/Mathlib/CategoryTheory/Limits/Yoneda.lean index 8f2956bb7a8ef..26ac00460355a 100644 --- a/Mathlib/CategoryTheory/Limits/Yoneda.lean +++ b/Mathlib/CategoryTheory/Limits/Yoneda.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Types diff --git a/Mathlib/CategoryTheory/Linear/Basic.lean b/Mathlib/CategoryTheory/Linear/Basic.lean index 0a45ae4d24a02..5f724dcf36cb9 100644 --- a/Mathlib/CategoryTheory/Linear/Basic.lean +++ b/Mathlib/CategoryTheory/Linear/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Algebra.Defs import Mathlib.Algebra.Module.Equiv.Defs diff --git a/Mathlib/CategoryTheory/Linear/FunctorCategory.lean b/Mathlib/CategoryTheory/Linear/FunctorCategory.lean index ed03809f158c5..54207426b1605 100644 --- a/Mathlib/CategoryTheory/Linear/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Linear/FunctorCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.FunctorCategory import Mathlib.CategoryTheory.Linear.Basic diff --git a/Mathlib/CategoryTheory/Linear/LinearFunctor.lean b/Mathlib/CategoryTheory/Linear/LinearFunctor.lean index c2ef88551f038..0e58e65be5bae 100644 --- a/Mathlib/CategoryTheory/Linear/LinearFunctor.lean +++ b/Mathlib/CategoryTheory/Linear/LinearFunctor.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor import Mathlib.CategoryTheory.Linear.Basic diff --git a/Mathlib/CategoryTheory/Linear/Yoneda.lean b/Mathlib/CategoryTheory/Linear/Yoneda.lean index 7022906c6dc3a..4836d3c76a695 100644 --- a/Mathlib/CategoryTheory/Linear/Yoneda.lean +++ b/Mathlib/CategoryTheory/Linear/Yoneda.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.CategoryTheory.Linear.Basic diff --git a/Mathlib/CategoryTheory/Monad/Adjunction.lean b/Mathlib/CategoryTheory/Monad/Adjunction.lean index fa27fe0d27eff..ebd45343a99da 100644 --- a/Mathlib/CategoryTheory/Monad/Adjunction.lean +++ b/Mathlib/CategoryTheory/Monad/Adjunction.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Adjunction.Reflective import Mathlib.CategoryTheory.Monad.Algebra diff --git a/Mathlib/CategoryTheory/Monad/Algebra.lean b/Mathlib/CategoryTheory/Monad/Algebra.lean index 7997a3d8c91e9..3c17e5635d306 100644 --- a/Mathlib/CategoryTheory/Monad/Algebra.lean +++ b/Mathlib/CategoryTheory/Monad/Algebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Monad.Basic import Mathlib.CategoryTheory.Adjunction.Basic diff --git a/Mathlib/CategoryTheory/Monad/Basic.lean b/Mathlib/CategoryTheory/Monad/Basic.lean index d50e030211dde..6a82f3d208edd 100644 --- a/Mathlib/CategoryTheory/Monad/Basic.lean +++ b/Mathlib/CategoryTheory/Monad/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta, Adam Topaz +Authors: Kim Morrison, Bhavik Mehta, Adam Topaz -/ import Mathlib.CategoryTheory.Functor.Category import Mathlib.CategoryTheory.Functor.FullyFaithful diff --git a/Mathlib/CategoryTheory/Monad/Limits.lean b/Mathlib/CategoryTheory/Monad/Limits.lean index f447048e82490..1e1128d105453 100644 --- a/Mathlib/CategoryTheory/Monad/Limits.lean +++ b/Mathlib/CategoryTheory/Monad/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta, Jack McKoen +Authors: Kim Morrison, Bhavik Mehta, Jack McKoen -/ import Mathlib.CategoryTheory.Monad.Adjunction import Mathlib.CategoryTheory.Adjunction.Limits diff --git a/Mathlib/CategoryTheory/Monoidal/Bimod.lean b/Mathlib/CategoryTheory/Monoidal/Bimod.lean index 23401b5af6406..b4118c7d293bf 100644 --- a/Mathlib/CategoryTheory/Monoidal/Bimod.lean +++ b/Mathlib/CategoryTheory/Monoidal/Bimod.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Oleksandr Manzyuk +Authors: Kim Morrison, Oleksandr Manzyuk -/ import Mathlib.CategoryTheory.Bicategory.Basic import Mathlib.CategoryTheory.Monoidal.Mon_ diff --git a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean index 27f88cae42c31..ecac5bcd3be12 100644 --- a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Discrete import Mathlib.CategoryTheory.Monoidal.NaturalTransformation diff --git a/Mathlib/CategoryTheory/Monoidal/Braided/Opposite.lean b/Mathlib/CategoryTheory/Monoidal/Braided/Opposite.lean index 91403618e1825..a4c907e15f044 100644 --- a/Mathlib/CategoryTheory/Monoidal/Braided/Opposite.lean +++ b/Mathlib/CategoryTheory/Monoidal/Braided/Opposite.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Lean FRO LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Monoidal.Opposite diff --git a/Mathlib/CategoryTheory/Monoidal/Category.lean b/Mathlib/CategoryTheory/Monoidal/Category.lean index 19ccf8685ca18..c38de64d692f4 100644 --- a/Mathlib/CategoryTheory/Monoidal/Category.lean +++ b/Mathlib/CategoryTheory/Monoidal/Category.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Jendrusch, Scott Morrison, Bhavik Mehta, Jakob von Raumer +Authors: Michael Jendrusch, Kim Morrison, Bhavik Mehta, Jakob von Raumer -/ import Mathlib.CategoryTheory.Functor.Trifunctor import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Monoidal/Center.lean b/Mathlib/CategoryTheory/Monoidal/Center.lean index 19df47cf77e91..5eab3c67802ba 100644 --- a/Mathlib/CategoryTheory/Monoidal/Center.lean +++ b/Mathlib/CategoryTheory/Monoidal/Center.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Functor.ReflectsIso diff --git a/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean b/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean index de0f9bff68b37..ef4ecbd8d3584 100644 --- a/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean +++ b/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Jendrusch, Scott Morrison, Bhavik Mehta, Jakob von Raumer +Authors: Michael Jendrusch, Kim Morrison, Bhavik Mehta, Jakob von Raumer -/ import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence diff --git a/Mathlib/CategoryTheory/Monoidal/CommMon_.lean b/Mathlib/CategoryTheory/Monoidal/CommMon_.lean index 7eaef1920b0fc..b8a3c549ea911 100644 --- a/Mathlib/CategoryTheory/Monoidal/CommMon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/CommMon_.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Monoidal.Mon_ diff --git a/Mathlib/CategoryTheory/Monoidal/Discrete.lean b/Mathlib/CategoryTheory/Monoidal/Discrete.lean index dbd834083cb6e..9ff8e09d5151e 100644 --- a/Mathlib/CategoryTheory/Monoidal/Discrete.lean +++ b/Mathlib/CategoryTheory/Monoidal/Discrete.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Hom.Defs import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/Monoidal/End.lean b/Mathlib/CategoryTheory/Monoidal/End.lean index 52c8651d1e0ed..5a48831f3a044 100644 --- a/Mathlib/CategoryTheory/Monoidal/End.lean +++ b/Mathlib/CategoryTheory/Monoidal/End.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Andrew Yang +Authors: Kim Morrison, Andrew Yang -/ import Mathlib.CategoryTheory.Monoidal.Functor diff --git a/Mathlib/CategoryTheory/Monoidal/Functor.lean b/Mathlib/CategoryTheory/Monoidal/Functor.lean index 019efca02f2f3..1cd5fbc682a6c 100644 --- a/Mathlib/CategoryTheory/Monoidal/Functor.lean +++ b/Mathlib/CategoryTheory/Monoidal/Functor.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Jendrusch, Scott Morrison, Bhavik Mehta +Authors: Michael Jendrusch, Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Monoidal.Category import Mathlib.CategoryTheory.Adjunction.FullyFaithful diff --git a/Mathlib/CategoryTheory/Monoidal/FunctorCategory.lean b/Mathlib/CategoryTheory/Monoidal/FunctorCategory.lean index 90286ae948670..5a69edb48708b 100644 --- a/Mathlib/CategoryTheory/Monoidal/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Monoidal/FunctorCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Functor.Category diff --git a/Mathlib/CategoryTheory/Monoidal/Functorial.lean b/Mathlib/CategoryTheory/Monoidal/Functorial.lean index 26bd834c33628..5f9d7be6fbb24 100644 --- a/Mathlib/CategoryTheory/Monoidal/Functorial.lean +++ b/Mathlib/CategoryTheory/Monoidal/Functorial.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Functor import Mathlib.CategoryTheory.Functor.Functorial diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/FunctorCategory.lean b/Mathlib/CategoryTheory/Monoidal/Internal/FunctorCategory.lean index 19c7811649daf..6d90406b86532 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/FunctorCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.CommMon_ import Mathlib.CategoryTheory.Monoidal.Comon_ diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Limits.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Limits.lean index 8986e18168ceb..53ddce8988862 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Limits.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Internal.FunctorCategory import Mathlib.CategoryTheory.Monoidal.Limits diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean index b196ef36ecbc6..2e6df6e377f89 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Monoidal.Basic import Mathlib.Algebra.Category.AlgebraCat.Basic diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean index 1c8d1b2ee61fc..00d58af2f33d2 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.MonCat.Basic import Mathlib.CategoryTheory.Monoidal.CommMon_ diff --git a/Mathlib/CategoryTheory/Monoidal/Limits.lean b/Mathlib/CategoryTheory/Monoidal/Limits.lean index 4ddc2b63e9618..e13b3fa646109 100644 --- a/Mathlib/CategoryTheory/Monoidal/Limits.lean +++ b/Mathlib/CategoryTheory/Monoidal/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Functorial import Mathlib.CategoryTheory.Monoidal.FunctorCategory diff --git a/Mathlib/CategoryTheory/Monoidal/Linear.lean b/Mathlib/CategoryTheory/Monoidal/Linear.lean index f736296f7147d..d9c475fc8dc58 100644 --- a/Mathlib/CategoryTheory/Monoidal/Linear.lean +++ b/Mathlib/CategoryTheory/Monoidal/Linear.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Linear.LinearFunctor import Mathlib.CategoryTheory.Monoidal.Preadditive diff --git a/Mathlib/CategoryTheory/Monoidal/Mod_.lean b/Mathlib/CategoryTheory/Monoidal/Mod_.lean index 79ddde1156f2d..bee5d1a324c2f 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mod_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mod_.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Mon_ diff --git a/Mathlib/CategoryTheory/Monoidal/Mon_.lean b/Mathlib/CategoryTheory/Monoidal/Mon_.lean index 292ec93b5a143..2202d88535f6a 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mon_.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Monoidal.Discrete diff --git a/Mathlib/CategoryTheory/Monoidal/NaturalTransformation.lean b/Mathlib/CategoryTheory/Monoidal/NaturalTransformation.lean index afec13d8a51df..37d92020f5dfd 100644 --- a/Mathlib/CategoryTheory/Monoidal/NaturalTransformation.lean +++ b/Mathlib/CategoryTheory/Monoidal/NaturalTransformation.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Adjunction.FullyFaithful import Mathlib.CategoryTheory.Monoidal.Functor diff --git a/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean b/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean index 3fc5f0c7ece26..9b23a5a2e1f1a 100644 --- a/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Simon Hudon +Authors: Kim Morrison, Simon Hudon -/ import Mathlib.CategoryTheory.Monoidal.Category import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts diff --git a/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Symmetric.lean b/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Symmetric.lean index eeea00aadcc4d..cd1586181796e 100644 --- a/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Symmetric.lean +++ b/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Symmetric.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Simon Hudon +Authors: Kim Morrison, Simon Hudon -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Monoidal.OfChosenFiniteProducts.Basic diff --git a/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean b/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean index 043177863cb9e..5395fd61f0a08 100644 --- a/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean +++ b/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Simon Hudon +Authors: Kim Morrison, Simon Hudon -/ import Mathlib.CategoryTheory.Monoidal.Braided.Basic import Mathlib.CategoryTheory.Limits.Preserves.Shapes.BinaryProducts diff --git a/Mathlib/CategoryTheory/Monoidal/Opposite.lean b/Mathlib/CategoryTheory/Monoidal/Opposite.lean index 6d15b4c0add4f..3866aa1f3735a 100644 --- a/Mathlib/CategoryTheory/Monoidal/Opposite.lean +++ b/Mathlib/CategoryTheory/Monoidal/Opposite.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Tactic.CategoryTheory.Monoidal.PureCoherence diff --git a/Mathlib/CategoryTheory/Monoidal/Preadditive.lean b/Mathlib/CategoryTheory/Monoidal/Preadditive.lean index 429a44d694e4c..7133ba4faabc0 100644 --- a/Mathlib/CategoryTheory/Monoidal/Preadditive.lean +++ b/Mathlib/CategoryTheory/Monoidal/Preadditive.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor import Mathlib.CategoryTheory.Monoidal.Functor diff --git a/Mathlib/CategoryTheory/Monoidal/Rigid/FunctorCategory.lean b/Mathlib/CategoryTheory/Monoidal/Rigid/FunctorCategory.lean index d458fd401af64..f520a501aff97 100644 --- a/Mathlib/CategoryTheory/Monoidal/Rigid/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Monoidal/Rigid/FunctorCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Rigid.Basic import Mathlib.CategoryTheory.Monoidal.FunctorCategory diff --git a/Mathlib/CategoryTheory/Monoidal/Rigid/OfEquivalence.lean b/Mathlib/CategoryTheory/Monoidal/Rigid/OfEquivalence.lean index 70e84ca5c9f1d..7eb07eb856049 100644 --- a/Mathlib/CategoryTheory/Monoidal/Rigid/OfEquivalence.lean +++ b/Mathlib/CategoryTheory/Monoidal/Rigid/OfEquivalence.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Rigid.Basic diff --git a/Mathlib/CategoryTheory/Monoidal/Tor.lean b/Mathlib/CategoryTheory/Monoidal/Tor.lean index 4f9a2de2e1361..51db95353b832 100644 --- a/Mathlib/CategoryTheory/Monoidal/Tor.lean +++ b/Mathlib/CategoryTheory/Monoidal/Tor.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Abelian.LeftDerived import Mathlib.CategoryTheory.Monoidal.Preadditive diff --git a/Mathlib/CategoryTheory/Monoidal/Transport.lean b/Mathlib/CategoryTheory/Monoidal/Transport.lean index c2ca8840916d1..19d755f6f034b 100644 --- a/Mathlib/CategoryTheory/Monoidal/Transport.lean +++ b/Mathlib/CategoryTheory/Monoidal/Transport.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.NaturalTransformation diff --git a/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean index 77a4726af04a5..9904eee364779 100644 --- a/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Jendrusch, Scott Morrison +Authors: Michael Jendrusch, Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Functor import Mathlib.CategoryTheory.ChosenFiniteProducts diff --git a/Mathlib/CategoryTheory/Monoidal/Types/Coyoneda.lean b/Mathlib/CategoryTheory/Monoidal/Types/Coyoneda.lean index 633d6872c7ad0..475acc453b566 100644 --- a/Mathlib/CategoryTheory/Monoidal/Types/Coyoneda.lean +++ b/Mathlib/CategoryTheory/Monoidal/Types/Coyoneda.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Jendrusch, Scott Morrison +Authors: Michael Jendrusch, Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Types.Basic import Mathlib.CategoryTheory.Monoidal.CoherenceLemmas diff --git a/Mathlib/CategoryTheory/Monoidal/Types/Symmetric.lean b/Mathlib/CategoryTheory/Monoidal/Types/Symmetric.lean index 69248ef1f0384..93ceaacca659f 100644 --- a/Mathlib/CategoryTheory/Monoidal/Types/Symmetric.lean +++ b/Mathlib/CategoryTheory/Monoidal/Types/Symmetric.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Jendrusch, Scott Morrison +Authors: Michael Jendrusch, Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.OfChosenFiniteProducts.Symmetric import Mathlib.CategoryTheory.Monoidal.Types.Basic diff --git a/Mathlib/CategoryTheory/NatIso.lean b/Mathlib/CategoryTheory/NatIso.lean index f90d1af88c7d0..2899c82c95db6 100644 --- a/Mathlib/CategoryTheory/NatIso.lean +++ b/Mathlib/CategoryTheory/NatIso.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Tim Baumann, Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Tim Baumann, Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.CategoryTheory.Functor.Category import Mathlib.CategoryTheory.Iso diff --git a/Mathlib/CategoryTheory/NatTrans.lean b/Mathlib/CategoryTheory/NatTrans.lean index 52013eb207f12..0c12f372eaeac 100644 --- a/Mathlib/CategoryTheory/NatTrans.lean +++ b/Mathlib/CategoryTheory/NatTrans.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Tim Baumann, Stephen Morgan, Scott Morrison, Floris van Doorn +Authors: Tim Baumann, Stephen Morgan, Kim Morrison, Floris van Doorn -/ import Mathlib.Tactic.CategoryTheory.Reassoc diff --git a/Mathlib/CategoryTheory/Noetherian.lean b/Mathlib/CategoryTheory/Noetherian.lean index 1065af138e416..6b7a78e563ca6 100644 --- a/Mathlib/CategoryTheory/Noetherian.lean +++ b/Mathlib/CategoryTheory/Noetherian.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.Lattice import Mathlib.CategoryTheory.EssentiallySmall diff --git a/Mathlib/CategoryTheory/Opposites.lean b/Mathlib/CategoryTheory/Opposites.lean index 901fde4a2fdcc..6d4f00e441da3 100644 --- a/Mathlib/CategoryTheory/Opposites.lean +++ b/Mathlib/CategoryTheory/Opposites.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison +Authors: Stephen Morgan, Kim Morrison -/ import Mathlib.CategoryTheory.Equivalence diff --git a/Mathlib/CategoryTheory/PEmpty.lean b/Mathlib/CategoryTheory/PEmpty.lean index 3f12752eb7f34..ee9546dc04437 100644 --- a/Mathlib/CategoryTheory/PEmpty.lean +++ b/Mathlib/CategoryTheory/PEmpty.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/PUnit.lean b/Mathlib/CategoryTheory/PUnit.lean index 2f3d7472d33df..d3c89945af0f3 100644 --- a/Mathlib/CategoryTheory/PUnit.lean +++ b/Mathlib/CategoryTheory/PUnit.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Functor.Const import Mathlib.CategoryTheory.DiscreteCategory diff --git a/Mathlib/CategoryTheory/PathCategory.lean b/Mathlib/CategoryTheory/PathCategory.lean index 126b988e6f0c5..4f0b3ec849790 100644 --- a/Mathlib/CategoryTheory/PathCategory.lean +++ b/Mathlib/CategoryTheory/PathCategory.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Quotient diff --git a/Mathlib/CategoryTheory/Pi/Basic.lean b/Mathlib/CategoryTheory/Pi/Basic.lean index caa1341b3caf6..166b83c21ef2a 100644 --- a/Mathlib/CategoryTheory/Pi/Basic.lean +++ b/Mathlib/CategoryTheory/Pi/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Simon Hudon, Scott Morrison +Authors: Simon Hudon, Kim Morrison -/ import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.NatIso diff --git a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean index 1a22be0cc03ff..adf26a8d7c01e 100644 --- a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean +++ b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Adam Topaz, Scott Morrison +Authors: Adam Topaz, Kim Morrison -/ import Mathlib.CategoryTheory.Limits.ExactFunctor import Mathlib.CategoryTheory.Limits.Preserves.Finite diff --git a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean index 095fb3ea4d5cf..5b06f3702ea3b 100644 --- a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean +++ b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Ext import Mathlib.CategoryTheory.Limits.Shapes.Biproducts diff --git a/Mathlib/CategoryTheory/Preadditive/HomOrthogonal.lean b/Mathlib/CategoryTheory/Preadditive/HomOrthogonal.lean index 4ff63ae23affb..4dfeacbfed5e2 100644 --- a/Mathlib/CategoryTheory/Preadditive/HomOrthogonal.lean +++ b/Mathlib/CategoryTheory/Preadditive/HomOrthogonal.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Linear.Basic import Mathlib.CategoryTheory.Preadditive.Biproducts diff --git a/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean b/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean index 4c932bdd5de89..9f756b5cdb943 100644 --- a/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jujian Zhang, Scott Morrison, Joël Riou +Authors: Jujian Zhang, Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Homology.QuasiIso import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex diff --git a/Mathlib/CategoryTheory/Preadditive/Mat.lean b/Mathlib/CategoryTheory/Preadditive/Mat.lean index d06b747a05fcf..d3d9783dc37c7 100644 --- a/Mathlib/CategoryTheory/Preadditive/Mat.lean +++ b/Mathlib/CategoryTheory/Preadditive/Mat.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.BigOperators.Pi diff --git a/Mathlib/CategoryTheory/Preadditive/Opposite.lean b/Mathlib/CategoryTheory/Preadditive/Opposite.lean index ccc1021d809aa..115a2764163aa 100644 --- a/Mathlib/CategoryTheory/Preadditive/Opposite.lean +++ b/Mathlib/CategoryTheory/Preadditive/Opposite.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Adam Topaz, Johan Commelin, Joël Riou +Authors: Kim Morrison, Adam Topaz, Johan Commelin, Joël Riou -/ import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor import Mathlib.Logic.Equiv.TransferInstance diff --git a/Mathlib/CategoryTheory/Preadditive/Projective.lean b/Mathlib/CategoryTheory/Preadditive/Projective.lean index 6cf35147c2231..e0900aad10375 100644 --- a/Mathlib/CategoryTheory/Preadditive/Projective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Projective.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.CategoryTheory.Adjunction.FullyFaithful import Mathlib.CategoryTheory.Adjunction.Limits diff --git a/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean b/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean index 8d947ea5ca55e..1447ce251a876 100644 --- a/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Joël Riou +Authors: Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Homology.QuasiIso import Mathlib.Algebra.Homology.SingleHomology diff --git a/Mathlib/CategoryTheory/Preadditive/Schur.lean b/Mathlib/CategoryTheory/Preadditive/Schur.lean index 5e012592ab269..407e246e350e0 100644 --- a/Mathlib/CategoryTheory/Preadditive/Schur.lean +++ b/Mathlib/CategoryTheory/Preadditive/Schur.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.Algebra.Group.Ext import Mathlib.CategoryTheory.Simple diff --git a/Mathlib/CategoryTheory/Preadditive/SingleObj.lean b/Mathlib/CategoryTheory/Preadditive/SingleObj.lean index da6a0ed13304f..a2b5d1a38ddaf 100644 --- a/Mathlib/CategoryTheory/Preadditive/SingleObj.lean +++ b/Mathlib/CategoryTheory/Preadditive/SingleObj.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.Basic import Mathlib.CategoryTheory.SingleObj diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Injective.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Injective.lean index d50174be5c41c..778a344fe5bbd 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Injective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Injective.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.CategoryTheory.Preadditive.Injective diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean index 2434e2bdb0a20..3db3048dcfe74 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.CategoryTheory.Preadditive.Projective diff --git a/Mathlib/CategoryTheory/Products/Associator.lean b/Mathlib/CategoryTheory/Products/Associator.lean index 232fe7f3c5ea2..041ecf6548890 100644 --- a/Mathlib/CategoryTheory/Products/Associator.lean +++ b/Mathlib/CategoryTheory/Products/Associator.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison +Authors: Stephen Morgan, Kim Morrison -/ import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Products/Basic.lean b/Mathlib/CategoryTheory/Products/Basic.lean index 449595eab85d3..c38b430629b3b 100644 --- a/Mathlib/CategoryTheory/Products/Basic.lean +++ b/Mathlib/CategoryTheory/Products/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison +Authors: Stephen Morgan, Kim Morrison -/ import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Functor.Const diff --git a/Mathlib/CategoryTheory/Products/Bifunctor.lean b/Mathlib/CategoryTheory/Products/Bifunctor.lean index 70e02805ce5ac..a0d335eb00794 100644 --- a/Mathlib/CategoryTheory/Products/Bifunctor.lean +++ b/Mathlib/CategoryTheory/Products/Bifunctor.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison +Authors: Stephen Morgan, Kim Morrison -/ import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Shift/Basic.lean b/Mathlib/CategoryTheory/Shift/Basic.lean index d830b0b79c97d..c8b2f4ddfaec9 100644 --- a/Mathlib/CategoryTheory/Shift/Basic.lean +++ b/Mathlib/CategoryTheory/Shift/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johan Commelin, Andrew Yang +Authors: Kim Morrison, Johan Commelin, Andrew Yang -/ import Mathlib.Algebra.Group.Basic import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Zero diff --git a/Mathlib/CategoryTheory/Simple.lean b/Mathlib/CategoryTheory/Simple.lean index 3545546a51b0b..619a1bdfe7847 100644 --- a/Mathlib/CategoryTheory/Simple.lean +++ b/Mathlib/CategoryTheory/Simple.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.ZeroMorphisms import Mathlib.CategoryTheory.Limits.Shapes.Kernels diff --git a/Mathlib/CategoryTheory/Subobject/Basic.lean b/Mathlib/CategoryTheory/Subobject/Basic.lean index 076606a7a3d8f..34c23433816f0 100644 --- a/Mathlib/CategoryTheory/Subobject/Basic.lean +++ b/Mathlib/CategoryTheory/Subobject/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Bhavik Mehta, Scott Morrison +Authors: Bhavik Mehta, Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.MonoOver import Mathlib.CategoryTheory.Skeletal @@ -45,7 +45,7 @@ See also ## Notes This development originally appeared in Bhavik Mehta's "Topos theory for Lean" repository, -and was ported to mathlib by Scott Morrison. +and was ported to mathlib by Kim Morrison. ### Implementation note diff --git a/Mathlib/CategoryTheory/Subobject/FactorThru.lean b/Mathlib/CategoryTheory/Subobject/FactorThru.lean index 5ad249474de0f..d4f891f44b528 100644 --- a/Mathlib/CategoryTheory/Subobject/FactorThru.lean +++ b/Mathlib/CategoryTheory/Subobject/FactorThru.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Bhavik Mehta, Scott Morrison +Authors: Bhavik Mehta, Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.Basic import Mathlib.CategoryTheory.Preadditive.Basic diff --git a/Mathlib/CategoryTheory/Subobject/Lattice.lean b/Mathlib/CategoryTheory/Subobject/Lattice.lean index 757a945d39a57..9fb683c1d2eaf 100644 --- a/Mathlib/CategoryTheory/Subobject/Lattice.lean +++ b/Mathlib/CategoryTheory/Subobject/Lattice.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Bhavik Mehta, Scott Morrison +Authors: Bhavik Mehta, Kim Morrison -/ import Mathlib.CategoryTheory.Functor.Currying import Mathlib.CategoryTheory.Subobject.FactorThru diff --git a/Mathlib/CategoryTheory/Subobject/Limits.lean b/Mathlib/CategoryTheory/Subobject/Limits.lean index 33f569c9bc1cc..26f73bd07b7d2 100644 --- a/Mathlib/CategoryTheory/Subobject/Limits.lean +++ b/Mathlib/CategoryTheory/Subobject/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Bhavik Mehta, Scott Morrison +Authors: Bhavik Mehta, Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.Lattice diff --git a/Mathlib/CategoryTheory/Subobject/MonoOver.lean b/Mathlib/CategoryTheory/Subobject/MonoOver.lean index 64cdb298ffa8e..e2cfc4d68b330 100644 --- a/Mathlib/CategoryTheory/Subobject/MonoOver.lean +++ b/Mathlib/CategoryTheory/Subobject/MonoOver.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Bhavik Mehta, Scott Morrison +Authors: Bhavik Mehta, Kim Morrison -/ import Mathlib.CategoryTheory.Adjunction.Over import Mathlib.CategoryTheory.Adjunction.Reflective @@ -28,7 +28,7 @@ and prove their basic properties and relationships. ## Notes This development originally appeared in Bhavik Mehta's "Topos theory for Lean" repository, -and was ported to mathlib by Scott Morrison. +and was ported to mathlib by Kim Morrison. -/ diff --git a/Mathlib/CategoryTheory/Subobject/Types.lean b/Mathlib/CategoryTheory/Subobject/Types.lean index 54ebdb2816d00..cb2e06f94b8b1 100644 --- a/Mathlib/CategoryTheory/Subobject/Types.lean +++ b/Mathlib/CategoryTheory/Subobject/Types.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.WellPowered import Mathlib.CategoryTheory.Types diff --git a/Mathlib/CategoryTheory/Subobject/WellPowered.lean b/Mathlib/CategoryTheory/Subobject/WellPowered.lean index 0a78979b8a9d0..399d029fc1211 100644 --- a/Mathlib/CategoryTheory/Subobject/WellPowered.lean +++ b/Mathlib/CategoryTheory/Subobject/WellPowered.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Subobject.Basic import Mathlib.CategoryTheory.EssentiallySmall diff --git a/Mathlib/CategoryTheory/Sums/Associator.lean b/Mathlib/CategoryTheory/Sums/Associator.lean index 214fda16c81c1..52868ef851d64 100644 --- a/Mathlib/CategoryTheory/Sums/Associator.lean +++ b/Mathlib/CategoryTheory/Sums/Associator.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Sums.Basic diff --git a/Mathlib/CategoryTheory/Sums/Basic.lean b/Mathlib/CategoryTheory/Sums/Basic.lean index 91a569cf79a16..51c5a75bafa70 100644 --- a/Mathlib/CategoryTheory/Sums/Basic.lean +++ b/Mathlib/CategoryTheory/Sums/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Equivalence diff --git a/Mathlib/CategoryTheory/Thin.lean b/Mathlib/CategoryTheory/Thin.lean index e44b1c223c030..a2c9cb1099b9c 100644 --- a/Mathlib/CategoryTheory/Thin.lean +++ b/Mathlib/CategoryTheory/Thin.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison, Bhavik Mehta. All rights reserved. +Copyright (c) 2019 Kim Morrison, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Bhavik Mehta +Authors: Kim Morrison, Bhavik Mehta -/ import Mathlib.CategoryTheory.Functor.Category import Mathlib.CategoryTheory.Iso diff --git a/Mathlib/CategoryTheory/Types.lean b/Mathlib/CategoryTheory/Types.lean index b7cab7670d304..b2b29e06f39d9 100644 --- a/Mathlib/CategoryTheory/Types.lean +++ b/Mathlib/CategoryTheory/Types.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Stephen Morgan, Scott Morrison, Johannes Hölzl +Authors: Stephen Morgan, Kim Morrison, Johannes Hölzl -/ import Mathlib.CategoryTheory.EpiMono import Mathlib.CategoryTheory.Functor.FullyFaithful diff --git a/Mathlib/CategoryTheory/UnivLE.lean b/Mathlib/CategoryTheory/UnivLE.lean index e6b8c95764011..0210136dcf7ea 100644 --- a/Mathlib/CategoryTheory/UnivLE.lean +++ b/Mathlib/CategoryTheory/UnivLE.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.UnivLE import Mathlib.CategoryTheory.EssentialImage diff --git a/Mathlib/CategoryTheory/Whiskering.lean b/Mathlib/CategoryTheory/Whiskering.lean index a674d50bcf341..7971db9d070c7 100644 --- a/Mathlib/CategoryTheory/Whiskering.lean +++ b/Mathlib/CategoryTheory/Whiskering.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Iso import Mathlib.CategoryTheory.Functor.Category diff --git a/Mathlib/CategoryTheory/Yoneda.lean b/Mathlib/CategoryTheory/Yoneda.lean index f3cbf94ce4ae3..9d0486e458589 100644 --- a/Mathlib/CategoryTheory/Yoneda.lean +++ b/Mathlib/CategoryTheory/Yoneda.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Functor.Hom import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/Combinatorics/Quiver/Basic.lean b/Mathlib/Combinatorics/Quiver/Basic.lean index 0000d08b93bfe..f0f77f70aa4b7 100644 --- a/Mathlib/Combinatorics/Quiver/Basic.lean +++ b/Mathlib/Combinatorics/Quiver/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 David Wärn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: David Wärn, Scott Morrison +Authors: David Wärn, Kim Morrison -/ import Mathlib.Data.Opposite diff --git a/Mathlib/Combinatorics/Quiver/Path.lean b/Mathlib/Combinatorics/Quiver/Path.lean index 08cf1779430aa..d87402e7fb551 100644 --- a/Mathlib/Combinatorics/Quiver/Path.lean +++ b/Mathlib/Combinatorics/Quiver/Path.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 David Wärn,. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: David Wärn, Scott Morrison +Authors: David Wärn, Kim Morrison -/ import Mathlib.Combinatorics.Quiver.Basic import Mathlib.Logic.Lemmas diff --git a/Mathlib/Control/EquivFunctor.lean b/Mathlib/Control/EquivFunctor.lean index 05e6050b3e91e..ecbf36b36a8a5 100644 --- a/Mathlib/Control/EquivFunctor.lean +++ b/Mathlib/Control/EquivFunctor.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Equiv.Defs import Mathlib.Tactic.Convert diff --git a/Mathlib/Control/EquivFunctor/Instances.lean b/Mathlib/Control/EquivFunctor/Instances.lean index 87b89a8ea37f9..13987af2679b9 100644 --- a/Mathlib/Control/EquivFunctor/Instances.lean +++ b/Mathlib/Control/EquivFunctor/Instances.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Fintype.Basic import Mathlib.Control.EquivFunctor diff --git a/Mathlib/Control/ULift.lean b/Mathlib/Control/ULift.lean index 785d0d187c5d7..f294e51cf20de 100644 --- a/Mathlib/Control/ULift.lean +++ b/Mathlib/Control/ULift.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Jannis Limperg +Authors: Kim Morrison, Jannis Limperg -/ import Mathlib.Init diff --git a/Mathlib/Data/Complex/Order.lean b/Mathlib/Data/Complex/Order.lean index f43e1f5666884..a9bc019f2b0bf 100644 --- a/Mathlib/Data/Complex/Order.lean +++ b/Mathlib/Data/Complex/Order.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Complex.Abs diff --git a/Mathlib/Data/Countable/Small.lean b/Mathlib/Data/Countable/Small.lean index c41b36c6d5183..72387f0c4a096 100644 --- a/Mathlib/Data/Countable/Small.lean +++ b/Mathlib/Data/Countable/Small.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Basic import Mathlib.Data.Countable.Defs diff --git a/Mathlib/Data/Finset/Fin.lean b/Mathlib/Data/Finset/Fin.lean index fbe5e4dd8b999..03b2036cefe0c 100644 --- a/Mathlib/Data/Finset/Fin.lean +++ b/Mathlib/Data/Finset/Fin.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Scott Morrison, Johan Commelin +Authors: Chris Hughes, Kim Morrison, Johan Commelin -/ import Mathlib.Data.Finset.Card diff --git a/Mathlib/Data/Finset/Functor.lean b/Mathlib/Data/Finset/Functor.lean index 2ae78966a4cd7..4319e4a6b1b3a 100644 --- a/Mathlib/Data/Finset/Functor.lean +++ b/Mathlib/Data/Finset/Functor.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yaël Dillies, Scott Morrison +Authors: Yaël Dillies, Kim Morrison -/ import Mathlib.Data.Finset.Lattice import Mathlib.Data.Finset.NAry diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index e6107678fa4e7..a9e39269baa78 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johannes Hölzl, Scott Morrison +Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.Group.Action.Basic diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index a41978fa0311d..70c91059b3738 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johannes Hölzl, Scott Morrison +Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.Group.Indicator import Mathlib.Algebra.Group.Submonoid.Basic diff --git a/Mathlib/Data/Finsupp/Pointwise.lean b/Mathlib/Data/Finsupp/Pointwise.lean index 609f2a8f9b146..059bf76ad5eed 100644 --- a/Mathlib/Data/Finsupp/Pointwise.lean +++ b/Mathlib/Data/Finsupp/Pointwise.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Module.Defs import Mathlib.Algebra.Ring.Pi diff --git a/Mathlib/Data/List/EditDistance/Bounds.lean b/Mathlib/Data/List/EditDistance/Bounds.lean index 5ad1aafb05254..7a20e9e681c9a 100644 --- a/Mathlib/Data/List/EditDistance/Bounds.lean +++ b/Mathlib/Data/List/EditDistance/Bounds.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Kim Liesinger. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Liesinger +Authors: Kim Morrison -/ import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Data.List.Infix diff --git a/Mathlib/Data/List/EditDistance/Defs.lean b/Mathlib/Data/List/EditDistance/Defs.lean index 2c9b6ab2d89f8..a52cf793066d8 100644 --- a/Mathlib/Data/List/EditDistance/Defs.lean +++ b/Mathlib/Data/List/EditDistance/Defs.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Kim Liesinger. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Liesinger +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Defs import Batteries.Data.List.Basic diff --git a/Mathlib/Data/List/EditDistance/Estimator.lean b/Mathlib/Data/List/EditDistance/Estimator.lean index 056d119f6af71..e000b2bc0d02b 100644 --- a/Mathlib/Data/List/EditDistance/Estimator.lean +++ b/Mathlib/Data/List/EditDistance/Estimator.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Kim Liesinger. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Liesinger +Authors: Kim Morrison -/ import Mathlib.Data.List.EditDistance.Bounds import Mathlib.Order.Estimator diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index 22b38b33b6259..240012da5d608 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Kenny Lau, Scott Morrison, Alex Keizer +Authors: Mario Carneiro, Kenny Lau, Kim Morrison, Alex Keizer -/ import Mathlib.Data.List.OfFn import Mathlib.Data.List.Range diff --git a/Mathlib/Data/List/Intervals.lean b/Mathlib/Data/List/Intervals.lean index fdfa018a9e884..c1419e19f2901 100644 --- a/Mathlib/Data/List/Intervals.lean +++ b/Mathlib/Data/List/Intervals.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.List.Lattice import Mathlib.Data.Bool.Basic diff --git a/Mathlib/Data/List/Lattice.lean b/Mathlib/Data/List/Lattice.lean index 93192b359af50..7c3ce41155f9f 100644 --- a/Mathlib/Data/List/Lattice.lean +++ b/Mathlib/Data/List/Lattice.lean @@ -2,7 +2,7 @@ Copyright (c) 2014 Parikshit Khanna. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro, -Scott Morrison +Kim Morrison -/ import Mathlib.Data.List.Basic diff --git a/Mathlib/Data/List/Range.lean b/Mathlib/Data/List/Range.lean index 66f26df43fc84..63ca906ece471 100644 --- a/Mathlib/Data/List/Range.lean +++ b/Mathlib/Data/List/Range.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Kenny Lau, Scott Morrison +Authors: Mario Carneiro, Kenny Lau, Kim Morrison -/ import Mathlib.Data.List.Chain import Mathlib.Data.List.Nodup diff --git a/Mathlib/Data/MLList/BestFirst.lean b/Mathlib/Data/MLList/BestFirst.lean index 04d8b676c5644..1eceab8e6500c 100644 --- a/Mathlib/Data/MLList/BestFirst.lean +++ b/Mathlib/Data/MLList/BestFirst.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Batteries.Data.MLList.Basic import Mathlib.Data.Prod.Lex diff --git a/Mathlib/Data/MLList/Dedup.lean b/Mathlib/Data/MLList/Dedup.lean index 870c13fb4f7ab..f608048a51890 100644 --- a/Mathlib/Data/MLList/Dedup.lean +++ b/Mathlib/Data/MLList/Dedup.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Batteries.Data.MLList.Basic diff --git a/Mathlib/Data/MLList/DepthFirst.lean b/Mathlib/Data/MLList/DepthFirst.lean index 4454d1b3d8207..cc407b0ef5c2d 100644 --- a/Mathlib/Data/MLList/DepthFirst.lean +++ b/Mathlib/Data/MLList/DepthFirst.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Batteries.Data.MLList.Basic import Mathlib.Control.Combinators diff --git a/Mathlib/Data/MLList/IO.lean b/Mathlib/Data/MLList/IO.lean index 3887b991697a4..caec83d6d5838 100644 --- a/Mathlib/Data/MLList/IO.lean +++ b/Mathlib/Data/MLList/IO.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Batteries.Data.MLList.Basic diff --git a/Mathlib/Data/MLList/Split.lean b/Mathlib/Data/MLList/Split.lean index 4a29154f9b6d2..2705ad27826e6 100644 --- a/Mathlib/Data/MLList/Split.lean +++ b/Mathlib/Data/MLList/Split.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Batteries.Data.MLList.Basic import Mathlib.Data.ULift diff --git a/Mathlib/Data/Matrix/Basis.lean b/Mathlib/Data/Matrix/Basis.lean index 1204f7bb9f157..01c7a8cf445b6 100644 --- a/Mathlib/Data/Matrix/Basis.lean +++ b/Mathlib/Data/Matrix/Basis.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Jalex Stark. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jalex Stark, Scott Morrison, Eric Wieser, Oliver Nash, Wen Yang +Authors: Jalex Stark, Kim Morrison, Eric Wieser, Oliver Nash, Wen Yang -/ import Mathlib.Data.Matrix.Basic import Mathlib.LinearAlgebra.Matrix.Trace diff --git a/Mathlib/Data/Matrix/DMatrix.lean b/Mathlib/Data/Matrix/DMatrix.lean index 64fcb5711e21b..d677b3ace646e 100644 --- a/Mathlib/Data/Matrix/DMatrix.lean +++ b/Mathlib/Data/Matrix/DMatrix.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Hom.Defs diff --git a/Mathlib/Data/Nat/Count.lean b/Mathlib/Data/Nat/Count.lean index c3e60e57f4397..cb2e2160ea3aa 100644 --- a/Mathlib/Data/Nat/Count.lean +++ b/Mathlib/Data/Nat/Count.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 Vladimir Goryachev. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yaël Dillies, Vladimir Goryachev, Kyle Miller, Scott Morrison, Eric Rodriguez +Authors: Yaël Dillies, Vladimir Goryachev, Kyle Miller, Kim Morrison, Eric Rodriguez -/ import Mathlib.SetTheory.Cardinal.Basic diff --git a/Mathlib/Data/Nat/Digits.lean b/Mathlib/Data/Nat/Digits.lean index cd2a1c41ebd01..f7955d0768276 100644 --- a/Mathlib/Data/Nat/Digits.lean +++ b/Mathlib/Data/Nat/Digits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Shing Tak Lam, Mario Carneiro +Authors: Kim Morrison, Shing Tak Lam, Mario Carneiro -/ import Mathlib.Algebra.BigOperators.Intervals import Mathlib.Algebra.BigOperators.Ring.List diff --git a/Mathlib/Data/Nat/Nth.lean b/Mathlib/Data/Nat/Nth.lean index a9e8888ac5127..13b3543cb9adc 100644 --- a/Mathlib/Data/Nat/Nth.lean +++ b/Mathlib/Data/Nat/Nth.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 Vladimir Goryachev. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yaël Dillies, Vladimir Goryachev, Kyle Miller, Scott Morrison, Eric Rodriguez +Authors: Yaël Dillies, Vladimir Goryachev, Kyle Miller, Kim Morrison, Eric Rodriguez -/ import Mathlib.Data.List.GetD import Mathlib.Data.Nat.Count diff --git a/Mathlib/Data/Opposite.lean b/Mathlib/Data/Opposite.lean index 9fedb11939f4b..2482808fe2c64 100644 --- a/Mathlib/Data/Opposite.lean +++ b/Mathlib/Data/Opposite.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Reid Barton, Simon Hudon, Kenny Lau +Authors: Kim Morrison, Reid Barton, Simon Hudon, Kenny Lau -/ import Mathlib.Logic.Equiv.Defs diff --git a/Mathlib/Data/PSigma/Order.lean b/Mathlib/Data/PSigma/Order.lean index 097dd92225da5..fe0d6b8051e5b 100644 --- a/Mathlib/Data/PSigma/Order.lean +++ b/Mathlib/Data/PSigma/Order.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Minchao Wu +Authors: Kim Morrison, Minchao Wu -/ import Mathlib.Data.Sigma.Lex import Mathlib.Order.BoundedOrder diff --git a/Mathlib/Data/Prod/Lex.lean b/Mathlib/Data/Prod/Lex.lean index f55eac2c324de..1a8b1f220c0f8 100644 --- a/Mathlib/Data/Prod/Lex.lean +++ b/Mathlib/Data/Prod/Lex.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Minchao Wu +Authors: Kim Morrison, Minchao Wu -/ import Mathlib.Order.BoundedOrder diff --git a/Mathlib/Data/Set/Operations.lean b/Mathlib/Data/Set/Operations.lean index 620c7afe1b44c..bed6dc9156d8b 100644 --- a/Mathlib/Data/Set/Operations.lean +++ b/Mathlib/Data/Set/Operations.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jeremy Avigad, Johannes Hölzl, Reid Barton, Scott Morrison, Patrick Massot, Kyle Miller, +Authors: Jeremy Avigad, Johannes Hölzl, Reid Barton, Kim Morrison, Patrick Massot, Kyle Miller, Minchao Wu, Yury Kudryashov, Floris van Doorn -/ import Mathlib.Data.SProd diff --git a/Mathlib/Data/Vector/Zip.lean b/Mathlib/Data/Vector/Zip.lean index eee02c2029439..f8c69ad4814b4 100644 --- a/Mathlib/Data/Vector/Zip.lean +++ b/Mathlib/Data/Vector/Zip.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Vector.Basic diff --git a/Mathlib/Deprecated/HashMap.lean b/Mathlib/Deprecated/HashMap.lean index a25770f9840a0..b5c815bd6e5a0 100644 --- a/Mathlib/Deprecated/HashMap.lean +++ b/Mathlib/Deprecated/HashMap.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init diff --git a/Mathlib/Deprecated/Subgroup.lean b/Mathlib/Deprecated/Subgroup.lean index cf7b641cb3195..b7c3f4795f8ec 100644 --- a/Mathlib/Deprecated/Subgroup.lean +++ b/Mathlib/Deprecated/Subgroup.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johannes Hölzl, Mitchell Rowett, Scott Morrison, Johan Commelin, Mario Carneiro, +Authors: Johannes Hölzl, Mitchell Rowett, Kim Morrison, Johan Commelin, Mario Carneiro, Michael Howes -/ import Mathlib.Algebra.Group.Subgroup.Basic diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean index b87c5e3e9a630..dd988d85c537d 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Sheaves.Presheaf import Mathlib.CategoryTheory.Adjunction.FullyFaithful diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean index 91683f96c4d14..3ce2bceb89768 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Geometry.RingedSpace.PresheafedSpace import Mathlib.Topology.Category.TopCat.Limits.Basic diff --git a/Mathlib/Geometry/RingedSpace/SheafedSpace.lean b/Mathlib/Geometry/RingedSpace/SheafedSpace.lean index 5ec030cd1628c..637e73b1c7aaa 100644 --- a/Mathlib/Geometry/RingedSpace/SheafedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/SheafedSpace.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Geometry.RingedSpace.PresheafedSpace.HasColimits import Mathlib.Geometry.RingedSpace.Stalks diff --git a/Mathlib/Geometry/RingedSpace/Stalks.lean b/Mathlib/Geometry/RingedSpace/Stalks.lean index 2bff8fe9dea93..858441ca519fa 100644 --- a/Mathlib/Geometry/RingedSpace/Stalks.lean +++ b/Mathlib/Geometry/RingedSpace/Stalks.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Geometry.RingedSpace.PresheafedSpace import Mathlib.CategoryTheory.Limits.Final diff --git a/Mathlib/GroupTheory/Coset/Basic.lean b/Mathlib/GroupTheory/Coset/Basic.lean index 2be6433c200fc..6143225812daa 100644 --- a/Mathlib/GroupTheory/Coset/Basic.lean +++ b/Mathlib/GroupTheory/Coset/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mitchell Rowett. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mitchell Rowett, Scott Morrison +Authors: Mitchell Rowett, Kim Morrison -/ import Mathlib.Algebra.Quotient import Mathlib.Algebra.Group.Subgroup.MulOpposite diff --git a/Mathlib/GroupTheory/Coset/Card.lean b/Mathlib/GroupTheory/Coset/Card.lean index 79fd105a82f88..67a686a06e9b1 100644 --- a/Mathlib/GroupTheory/Coset/Card.lean +++ b/Mathlib/GroupTheory/Coset/Card.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mitchell Rowett. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mitchell Rowett, Scott Morrison +Authors: Mitchell Rowett, Kim Morrison -/ import Mathlib.GroupTheory.Coset.Basic import Mathlib.SetTheory.Cardinal.Finite diff --git a/Mathlib/Lean/CoreM.lean b/Mathlib/Lean/CoreM.lean index 9a1cceb3fcd0a..475e0a4f41f08 100644 --- a/Mathlib/Lean/CoreM.lean +++ b/Mathlib/Lean/CoreM.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Tactic.ToExpr diff --git a/Mathlib/Lean/Expr.lean b/Mathlib/Lean/Expr.lean index f95a20189c59f..fa0ec85aea5d0 100644 --- a/Mathlib/Lean/Expr.lean +++ b/Mathlib/Lean/Expr.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Simon Hudon, Scott Morrison, Keeley Hoek, Robert Y. Lewis, Floris van Doorn +Authors: Mario Carneiro, Simon Hudon, Kim Morrison, Keeley Hoek, Robert Y. Lewis, Floris van Doorn -/ import Mathlib.Lean.Expr.Basic import Mathlib.Lean.Expr.ReplaceRec diff --git a/Mathlib/Lean/Expr/Basic.lean b/Mathlib/Lean/Expr/Basic.lean index cd4f02368e68b..add7ca2edafdb 100644 --- a/Mathlib/Lean/Expr/Basic.lean +++ b/Mathlib/Lean/Expr/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Simon Hudon, Scott Morrison, Keeley Hoek, Robert Y. Lewis, +Authors: Mario Carneiro, Simon Hudon, Kim Morrison, Keeley Hoek, Robert Y. Lewis, Floris van Doorn, Edward Ayers, Arthur Paulino -/ import Mathlib.Init diff --git a/Mathlib/Lean/Expr/ReplaceRec.lean b/Mathlib/Lean/Expr/ReplaceRec.lean index 80f1f08324276..185dbe0ba8785 100644 --- a/Mathlib/Lean/Expr/ReplaceRec.lean +++ b/Mathlib/Lean/Expr/ReplaceRec.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Simon Hudon, Scott Morrison, Keeley Hoek, Robert Y. Lewis, +Authors: Mario Carneiro, Simon Hudon, Kim Morrison, Keeley Hoek, Robert Y. Lewis, Floris van Doorn, Edward Ayers -/ import Lean.Expr diff --git a/Mathlib/Lean/LocalContext.lean b/Mathlib/Lean/LocalContext.lean index 5bc891c5cdf0b..3c410ec6b63e6 100644 --- a/Mathlib/Lean/LocalContext.lean +++ b/Mathlib/Lean/LocalContext.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.LocalContext diff --git a/Mathlib/Lean/Meta/Basic.lean b/Mathlib/Lean/Meta/Basic.lean index a8066da2f4022..71d36a1cdcc99 100644 --- a/Mathlib/Lean/Meta/Basic.lean +++ b/Mathlib/Lean/Meta/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Meta.AppBuilder diff --git a/Mathlib/Lean/Meta/DiscrTree.lean b/Mathlib/Lean/Meta/DiscrTree.lean index c20618862b96c..4698847cefc5a 100644 --- a/Mathlib/Lean/Meta/DiscrTree.lean +++ b/Mathlib/Lean/Meta/DiscrTree.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Meta.DiscrTree diff --git a/Mathlib/Lean/Meta/Simp.lean b/Mathlib/Lean/Meta/Simp.lean index 19d5c973616f2..5f38f103a0dcc 100644 --- a/Mathlib/Lean/Meta/Simp.lean +++ b/Mathlib/Lean/Meta/Simp.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Gabriel Ebner, Floris van Doorn +Authors: Kim Morrison, Gabriel Ebner, Floris van Doorn -/ import Mathlib.Init import Lean.Elab.Tactic.Simp diff --git a/Mathlib/Lean/Name.lean b/Mathlib/Lean/Name.lean index 268d785610641..4f3b4e06b54e3 100644 --- a/Mathlib/Lean/Name.lean +++ b/Mathlib/Lean/Name.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Meta.Match.MatcherInfo diff --git a/Mathlib/LinearAlgebra/Dimension/Basic.lean b/Mathlib/LinearAlgebra/Dimension/Basic.lean index 673047ce643a6..9508cc5b7d60c 100644 --- a/Mathlib/LinearAlgebra/Dimension/Basic.lean +++ b/Mathlib/LinearAlgebra/Dimension/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Scott Morrison +Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Kim Morrison -/ import Mathlib.LinearAlgebra.LinearIndependent diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index f34b954448f30..2cf63df0ef942 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Scott Morrison, Chris Hughes, Anne Baanen +Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Kim Morrison, Chris Hughes, Anne Baanen -/ import Mathlib.LinearAlgebra.Dimension.Free import Mathlib.Algebra.Module.Torsion diff --git a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean index c18b030de59b8..81356f0bed052 100644 --- a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean +++ b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean @@ -2,7 +2,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, -Scott Morrison, Chris Hughes, Anne Baanen, Junyan Xu +Kim Morrison, Chris Hughes, Anne Baanen, Junyan Xu -/ import Mathlib.LinearAlgebra.Basis.VectorSpace import Mathlib.LinearAlgebra.Dimension.Finite diff --git a/Mathlib/LinearAlgebra/Dimension/Finite.lean b/Mathlib/LinearAlgebra/Dimension/Finite.lean index 48217a2ace216..32cbe00cac733 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finite.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finite.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Scott Morrison +Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Kim Morrison -/ import Mathlib.Algebra.Module.Torsion import Mathlib.SetTheory.Cardinal.Cofinality diff --git a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean index b7d2c4c6e0497..aecd0ad209da8 100644 --- a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.LinearAlgebra.Dimension.Finrank import Mathlib.LinearAlgebra.InvariantBasisNumber diff --git a/Mathlib/LinearAlgebra/InvariantBasisNumber.lean b/Mathlib/LinearAlgebra/InvariantBasisNumber.lean index 2e8c75c44c9d9..fb28e11886df5 100644 --- a/Mathlib/LinearAlgebra/InvariantBasisNumber.lean +++ b/Mathlib/LinearAlgebra/InvariantBasisNumber.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Markus Himmel, Scott Morrison +Authors: Markus Himmel, Kim Morrison -/ import Mathlib.RingTheory.OrzechProperty import Mathlib.RingTheory.Ideal.Quotient diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean index cffadee4baad5..83b4e6ed3bec2 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.LinearAlgebra.Matrix.Adjugate import Mathlib.RingTheory.PolynomialAlgebra diff --git a/Mathlib/LinearAlgebra/Matrix/InvariantBasisNumber.lean b/Mathlib/LinearAlgebra/Matrix/InvariantBasisNumber.lean index 5509163c9fd47..a424543278ed7 100644 --- a/Mathlib/LinearAlgebra/Matrix/InvariantBasisNumber.lean +++ b/Mathlib/LinearAlgebra/Matrix/InvariantBasisNumber.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.LinearAlgebra.Matrix.ToLin import Mathlib.LinearAlgebra.InvariantBasisNumber diff --git a/Mathlib/LinearAlgebra/TensorProduct/Tower.lean b/Mathlib/LinearAlgebra/TensorProduct/Tower.lean index da36cbf10939d..5ed4fbb0c5ba5 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Tower.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Tower.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johan Commelin, Eric Wieser +Authors: Kim Morrison, Johan Commelin, Eric Wieser -/ import Mathlib.Algebra.Algebra.Tower import Mathlib.LinearAlgebra.TensorProduct.Basic diff --git a/Mathlib/Logic/Equiv/Functor.lean b/Mathlib/Logic/Equiv/Functor.lean index e0f6ec21b8efa..203a282c37bf9 100644 --- a/Mathlib/Logic/Equiv/Functor.lean +++ b/Mathlib/Logic/Equiv/Functor.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Simon Hudon, Scott Morrison +Authors: Johan Commelin, Simon Hudon, Kim Morrison -/ import Mathlib.Control.Bifunctor import Mathlib.Logic.Equiv.Defs diff --git a/Mathlib/Logic/Small/Basic.lean b/Mathlib/Logic/Small/Basic.lean index f02a85cb0ee6a..7024044988faa 100644 --- a/Mathlib/Logic/Small/Basic.lean +++ b/Mathlib/Logic/Small/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Defs import Mathlib.Logic.Equiv.Set diff --git a/Mathlib/Logic/Small/Defs.lean b/Mathlib/Logic/Small/Defs.lean index c93c2ba60d7d1..51d7142ca561b 100644 --- a/Mathlib/Logic/Small/Defs.lean +++ b/Mathlib/Logic/Small/Defs.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Equiv.Defs import Mathlib.Tactic.MkIffOfInductiveProp diff --git a/Mathlib/Logic/Small/Group.lean b/Mathlib/Logic/Small/Group.lean index 3ec5b0486b284..4242a307e776b 100644 --- a/Mathlib/Logic/Small/Group.lean +++ b/Mathlib/Logic/Small/Group.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Defs import Mathlib.Logic.Equiv.TransferInstance diff --git a/Mathlib/Logic/Small/List.lean b/Mathlib/Logic/Small/List.lean index ef015f7089a1f..13b6fd0b0469a 100644 --- a/Mathlib/Logic/Small/List.lean +++ b/Mathlib/Logic/Small/List.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Basic import Mathlib.Data.Vector.Basic diff --git a/Mathlib/Logic/Small/Module.lean b/Mathlib/Logic/Small/Module.lean index 4280027faf576..8dd1444204daa 100644 --- a/Mathlib/Logic/Small/Module.lean +++ b/Mathlib/Logic/Small/Module.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Group import Mathlib.Logic.Small.Ring diff --git a/Mathlib/Logic/Small/Ring.lean b/Mathlib/Logic/Small/Ring.lean index 2c55cfd01e1c5..d64f33557a2c1 100644 --- a/Mathlib/Logic/Small/Ring.lean +++ b/Mathlib/Logic/Small/Ring.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Defs import Mathlib.Logic.Equiv.TransferInstance diff --git a/Mathlib/Logic/UnivLE.lean b/Mathlib/Logic/UnivLE.lean index a3a3a3c3e622a..d9f43bcd66b60 100644 --- a/Mathlib/Logic/UnivLE.lean +++ b/Mathlib/Logic/UnivLE.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Logic.Small.Defs diff --git a/Mathlib/NumberTheory/LucasLehmer.lean b/Mathlib/NumberTheory/LucasLehmer.lean index 53a9581878744..eed5e96c27d87 100644 --- a/Mathlib/NumberTheory/LucasLehmer.lean +++ b/Mathlib/NumberTheory/LucasLehmer.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Scott Morrison, Ainsley Pahljina +Authors: Mario Carneiro, Kim Morrison, Ainsley Pahljina -/ import Mathlib.RingTheory.Fintype @@ -24,7 +24,7 @@ primes using `lucas_lehmer_sufficiency`. ## History This development began as a student project by Ainsley Pahljina, -and was then cleaned up for mathlib by Scott Morrison. +and was then cleaned up for mathlib by Kim Morrison. The tactic for certified computation of Lucas-Lehmer residues was provided by Mario Carneiro. This tactic was ported by Thomas Murrills to Lean 4, and then it was converted to a `norm_num` extension and made to use kernel reductions by Kyle Miller. diff --git a/Mathlib/Order/Estimator.lean b/Mathlib/Order/Estimator.lean index 6cbb66c675781..29676a5330f47 100644 --- a/Mathlib/Order/Estimator.lean +++ b/Mathlib/Order/Estimator.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Kim Liesinger. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Liesinger +Authors: Kim Morrison -/ import Mathlib.Data.Set.Operations import Mathlib.Order.Heyting.Basic diff --git a/Mathlib/Order/Interval/Finset/Basic.lean b/Mathlib/Order/Interval/Finset/Basic.lean index baa9a5f67300a..8964e28ae8b2a 100644 --- a/Mathlib/Order/Interval/Finset/Basic.lean +++ b/Mathlib/Order/Interval/Finset/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Yaël Dillies +Authors: Kim Morrison, Yaël Dillies -/ import Mathlib.Order.Cover import Mathlib.Order.Interval.Finset.Defs diff --git a/Mathlib/Order/Interval/Set/Image.lean b/Mathlib/Order/Interval/Set/Image.lean index 0b194b81b848d..61ca9a56a17ad 100644 --- a/Mathlib/Order/Interval/Set/Image.lean +++ b/Mathlib/Order/Interval/Set/Image.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Kim Liesinger. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Liesinger, Yaël Dillies +Authors: Kim Morrison, Yaël Dillies -/ import Mathlib.Order.Interval.Set.Basic import Mathlib.Data.Set.Function diff --git a/Mathlib/Order/PartialSups.lean b/Mathlib/Order/PartialSups.lean index cfb8d50271716..5fbe0f73945d5 100644 --- a/Mathlib/Order/PartialSups.lean +++ b/Mathlib/Order/PartialSups.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Finset.Lattice import Mathlib.Order.Hom.Basic diff --git a/Mathlib/RepresentationTheory/Action/Basic.lean b/Mathlib/RepresentationTheory/Action/Basic.lean index 7f3481318aa92..e09c00af54f4e 100644 --- a/Mathlib/RepresentationTheory/Action/Basic.lean +++ b/Mathlib/RepresentationTheory/Action/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Grp.Basic import Mathlib.CategoryTheory.SingleObj diff --git a/Mathlib/RepresentationTheory/Action/Concrete.lean b/Mathlib/RepresentationTheory/Action/Concrete.lean index 3c2ec6686bc7d..e2ebc3a42dff7 100644 --- a/Mathlib/RepresentationTheory/Action/Concrete.lean +++ b/Mathlib/RepresentationTheory/Action/Concrete.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Group.Action.Pi import Mathlib.CategoryTheory.FintypeCat diff --git a/Mathlib/RepresentationTheory/Action/Limits.lean b/Mathlib/RepresentationTheory/Action/Limits.lean index 60d9a97e9d74f..3978ae5ce16ce 100644 --- a/Mathlib/RepresentationTheory/Action/Limits.lean +++ b/Mathlib/RepresentationTheory/Action/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Abelian.FunctorCategory import Mathlib.CategoryTheory.Abelian.Transfer diff --git a/Mathlib/RepresentationTheory/Action/Monoidal.lean b/Mathlib/RepresentationTheory/Action/Monoidal.lean index 7b6b4bfa684b9..e9ebdc2e143b1 100644 --- a/Mathlib/RepresentationTheory/Action/Monoidal.lean +++ b/Mathlib/RepresentationTheory/Action/Monoidal.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Monoidal.Linear import Mathlib.CategoryTheory.Monoidal.Rigid.FunctorCategory diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index b45a965988b28..b19b49f0e400b 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.FGModuleCat.Limits import Mathlib.CategoryTheory.Monoidal.Rigid.Braided diff --git a/Mathlib/RepresentationTheory/Maschke.lean b/Mathlib/RepresentationTheory/Maschke.lean index f35efe285d18d..7eaec76c225f9 100644 --- a/Mathlib/RepresentationTheory/Maschke.lean +++ b/Mathlib/RepresentationTheory/Maschke.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.MonoidAlgebra.Basic import Mathlib.LinearAlgebra.Basis.VectorSpace diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index 1918020135dc9..223f8229607a1 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.ModuleCat.Adjunctions import Mathlib.Algebra.Category.ModuleCat.Limits diff --git a/Mathlib/RingTheory/Fintype.lean b/Mathlib/RingTheory/Fintype.lean index ea2719912c171..9ee3bc2a315f2 100644 --- a/Mathlib/RingTheory/Fintype.lean +++ b/Mathlib/RingTheory/Fintype.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Fintype.Units import Mathlib.Data.ZMod.Basic diff --git a/Mathlib/RingTheory/MatrixAlgebra.lean b/Mathlib/RingTheory/MatrixAlgebra.lean index 8e82eb433d12a..4a71967b89d79 100644 --- a/Mathlib/RingTheory/MatrixAlgebra.lean +++ b/Mathlib/RingTheory/MatrixAlgebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Eric Wieser +Authors: Kim Morrison, Eric Wieser -/ import Mathlib.Data.Matrix.Basis import Mathlib.RingTheory.TensorProduct.Basic diff --git a/Mathlib/RingTheory/Polynomial/Bernstein.lean b/Mathlib/RingTheory/Polynomial/Bernstein.lean index d3efc2a2b5cb0..8cae9a4f38a0d 100644 --- a/Mathlib/RingTheory/Polynomial/Bernstein.lean +++ b/Mathlib/RingTheory/Polynomial/Bernstein.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.MvPolynomial.PDeriv import Mathlib.Algebra.Polynomial.AlgebraMap diff --git a/Mathlib/RingTheory/Polynomial/IntegralNormalization.lean b/Mathlib/RingTheory/Polynomial/IntegralNormalization.lean index 467b55e7f137e..b8383bd8e208a 100644 --- a/Mathlib/RingTheory/Polynomial/IntegralNormalization.lean +++ b/Mathlib/RingTheory/Polynomial/IntegralNormalization.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker +Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Polynomial.AlgebraMap import Mathlib.Algebra.Polynomial.Degree.Lemmas diff --git a/Mathlib/RingTheory/Polynomial/Pochhammer.lean b/Mathlib/RingTheory/Polynomial/Pochhammer.lean index f4d2df4b5c382..a96e49ebd3495 100644 --- a/Mathlib/RingTheory/Polynomial/Pochhammer.lean +++ b/Mathlib/RingTheory/Polynomial/Pochhammer.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Polynomial.Degree.Definitions import Mathlib.Algebra.Polynomial.Eval diff --git a/Mathlib/RingTheory/PolynomialAlgebra.lean b/Mathlib/RingTheory/PolynomialAlgebra.lean index d21058ee4247c..410b46c3aec39 100644 --- a/Mathlib/RingTheory/PolynomialAlgebra.lean +++ b/Mathlib/RingTheory/PolynomialAlgebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Polynomial.AlgebraMap import Mathlib.Data.Matrix.Basis diff --git a/Mathlib/RingTheory/TensorProduct/Basic.lean b/Mathlib/RingTheory/TensorProduct/Basic.lean index 31824342a497b..3bddb995b0910 100644 --- a/Mathlib/RingTheory/TensorProduct/Basic.lean +++ b/Mathlib/RingTheory/TensorProduct/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Johan Commelin +Authors: Kim Morrison, Johan Commelin -/ import Mathlib.GroupTheory.MonoidLocalization.Basic import Mathlib.LinearAlgebra.FreeModule.Basic diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index 2231078014db3..f6b0a8b89caf6 100644 --- a/Mathlib/SetTheory/Game/Basic.lean +++ b/Mathlib/SetTheory/Game/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Mario Carneiro, Isabel Longbottom, Scott Morrison, Apurva Nakade +Authors: Reid Barton, Mario Carneiro, Isabel Longbottom, Kim Morrison, Apurva Nakade -/ import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Ring.Int diff --git a/Mathlib/SetTheory/Game/Domineering.lean b/Mathlib/SetTheory/Game/Domineering.lean index e542ce9026c9b..e2301050c9961 100644 --- a/Mathlib/SetTheory/Game/Domineering.lean +++ b/Mathlib/SetTheory/Game/Domineering.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.SetTheory.Game.State diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 7307ca95f4c59..94f9ebf8cd866 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Mario Carneiro, Isabel Longbottom, Scott Morrison +Authors: Reid Barton, Mario Carneiro, Isabel Longbottom, Kim Morrison -/ import Mathlib.Algebra.Order.ZeroLEOne import Mathlib.Data.List.InsertNth diff --git a/Mathlib/SetTheory/Game/Short.lean b/Mathlib/SetTheory/Game/Short.lean index a95edd2eb7f21..1d55f6247f452 100644 --- a/Mathlib/SetTheory/Game/Short.lean +++ b/Mathlib/SetTheory/Game/Short.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Data.Fintype.Basic diff --git a/Mathlib/SetTheory/Game/State.lean b/Mathlib/SetTheory/Game/State.lean index 79423b09551f8..d7871744adc58 100644 --- a/Mathlib/SetTheory/Game/State.lean +++ b/Mathlib/SetTheory/Game/State.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.SetTheory.Game.Short diff --git a/Mathlib/SetTheory/Surreal/Basic.lean b/Mathlib/SetTheory/Surreal/Basic.lean index bbb97f8232f9c..6b466f6a32173 100644 --- a/Mathlib/SetTheory/Surreal/Basic.lean +++ b/Mathlib/SetTheory/Surreal/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Scott Morrison +Authors: Mario Carneiro, Kim Morrison -/ import Mathlib.Algebra.Order.Hom.Monoid import Mathlib.SetTheory.Game.Ordinal diff --git a/Mathlib/SetTheory/Surreal/Multiplication.lean b/Mathlib/SetTheory/Surreal/Multiplication.lean index 29f0f225bedb8..581ee2b7acc94 100644 --- a/Mathlib/SetTheory/Surreal/Multiplication.lean +++ b/Mathlib/SetTheory/Surreal/Multiplication.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Theodore Hwa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Scott Morrison, Violeta Hernández Palacios, Junyan Xu, Theodore Hwa +Authors: Mario Carneiro, Kim Morrison, Violeta Hernández Palacios, Junyan Xu, Theodore Hwa -/ import Mathlib.Logic.Hydra import Mathlib.SetTheory.Surreal.Basic diff --git a/Mathlib/Tactic/Abel.lean b/Mathlib/Tactic/Abel.lean index a0c5c9ec31aff..5ccbf7d2844fd 100644 --- a/Mathlib/Tactic/Abel.lean +++ b/Mathlib/Tactic/Abel.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Scott Morrison +Authors: Mario Carneiro, Kim Morrison -/ import Mathlib.Tactic.NormNum.Basic import Mathlib.Tactic.TryThis diff --git a/Mathlib/Tactic/ApplyCongr.lean b/Mathlib/Tactic/ApplyCongr.lean index f2ae29d7ee7c3..ee79d93eba02a 100644 --- a/Mathlib/Tactic/ApplyCongr.lean +++ b/Mathlib/Tactic/ApplyCongr.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Lucas Allen, Scott Morrison +Authors: Lucas Allen, Kim Morrison -/ import Mathlib.Tactic.Conv diff --git a/Mathlib/Tactic/ApplyFun.lean b/Mathlib/Tactic/ApplyFun.lean index e9aa791b2eb59..2b55685474bb7 100644 --- a/Mathlib/Tactic/ApplyFun.lean +++ b/Mathlib/Tactic/ApplyFun.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Keeley Hoek, Patrick Massot, Scott Morrison +Authors: Keeley Hoek, Patrick Massot, Kim Morrison -/ import Mathlib.Lean.Expr.Basic import Mathlib.Order.Monotone.Basic diff --git a/Mathlib/Tactic/CategoryTheory/Coherence.lean b/Mathlib/Tactic/CategoryTheory/Coherence.lean index 796dc395f7e3c..a479585f2c608 100644 --- a/Mathlib/Tactic/CategoryTheory/Coherence.lean +++ b/Mathlib/Tactic/CategoryTheory/Coherence.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Yuma Mizuno, Oleksandr Manzyuk +Authors: Kim Morrison, Yuma Mizuno, Oleksandr Manzyuk -/ import Mathlib.CategoryTheory.Monoidal.Free.Coherence import Mathlib.Lean.Meta diff --git a/Mathlib/Tactic/CategoryTheory/Elementwise.lean b/Mathlib/Tactic/CategoryTheory/Elementwise.lean index d59751db664cf..6ed09d82703a2 100644 --- a/Mathlib/Tactic/CategoryTheory/Elementwise.lean +++ b/Mathlib/Tactic/CategoryTheory/Elementwise.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Kyle Miller +Authors: Kim Morrison, Kyle Miller -/ import Mathlib.CategoryTheory.ConcreteCategory.Basic @@ -29,7 +29,7 @@ For more details, see the documentation attached to the `syntax` declaration. ## Implementation This closely follows the implementation of the `@[reassoc]` attribute, due to Simon Hudon and -reimplemented by Scott Morrison in Lean 4. +reimplemented by Kim Morrison in Lean 4. -/ open Lean Meta Elab Tactic diff --git a/Mathlib/Tactic/CategoryTheory/MonoidalComp.lean b/Mathlib/Tactic/CategoryTheory/MonoidalComp.lean index a2421b49f726b..316faec90eedf 100644 --- a/Mathlib/Tactic/CategoryTheory/MonoidalComp.lean +++ b/Mathlib/Tactic/CategoryTheory/MonoidalComp.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Yuma Mizuno, Oleksandr Manzyuk +Authors: Kim Morrison, Yuma Mizuno, Oleksandr Manzyuk -/ import Mathlib.CategoryTheory.Monoidal.Category diff --git a/Mathlib/Tactic/CategoryTheory/Reassoc.lean b/Mathlib/Tactic/CategoryTheory/Reassoc.lean index eedc010454f06..f76eba34bf8a9 100644 --- a/Mathlib/Tactic/CategoryTheory/Reassoc.lean +++ b/Mathlib/Tactic/CategoryTheory/Reassoc.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Functor.Basic import Mathlib.Util.AddRelatedDecl diff --git a/Mathlib/Tactic/CategoryTheory/Slice.lean b/Mathlib/Tactic/CategoryTheory/Slice.lean index 60a77786bac0a..f3f88410158c6 100644 --- a/Mathlib/Tactic/CategoryTheory/Slice.lean +++ b/Mathlib/Tactic/CategoryTheory/Slice.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Category.Basic diff --git a/Mathlib/Tactic/Common.lean b/Mathlib/Tactic/Common.lean index 69682e5554d89..f9c7a25eb782c 100644 --- a/Mathlib/Tactic/Common.lean +++ b/Mathlib/Tactic/Common.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ -- First import Aesop and Qq diff --git a/Mathlib/Tactic/Constructor.lean b/Mathlib/Tactic/Constructor.lean index 6ba7e4aee3325..64adccae545b7 100644 --- a/Mathlib/Tactic/Constructor.lean +++ b/Mathlib/Tactic/Constructor.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Newell Jensen +Authors: Kim Morrison, Newell Jensen -/ import Mathlib.Init import Lean.Elab.SyntheticMVars diff --git a/Mathlib/Tactic/Convert.lean b/Mathlib/Tactic/Convert.lean index aa2d570e1a2a9..c0dcc20b97221 100644 --- a/Mathlib/Tactic/Convert.lean +++ b/Mathlib/Tactic/Convert.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Kyle Miller +Authors: Kim Morrison, Kyle Miller -/ import Mathlib.Tactic.CongrExclamation diff --git a/Mathlib/Tactic/FinCases.lean b/Mathlib/Tactic/FinCases.lean index 493404b8844af..5a59db53e67bd 100644 --- a/Mathlib/Tactic/FinCases.lean +++ b/Mathlib/Tactic/FinCases.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Hanting Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Hanting Zhang +Authors: Kim Morrison, Hanting Zhang -/ import Mathlib.Tactic.Core import Mathlib.Lean.Expr.Basic diff --git a/Mathlib/Tactic/Generalize.lean b/Mathlib/Tactic/Generalize.lean index bcd97b1c34af3..20250ad5f6e41 100644 --- a/Mathlib/Tactic/Generalize.lean +++ b/Mathlib/Tactic/Generalize.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Lean FRO, LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Elab.Binders diff --git a/Mathlib/Tactic/Hint.lean b/Mathlib/Tactic/Hint.lean index 6194f2cbaaabb..8df08cd79a07e 100644 --- a/Mathlib/Tactic/Hint.lean +++ b/Mathlib/Tactic/Hint.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Lean.Meta.Tactic.TryThis import Batteries.Linter.UnreachableTactic diff --git a/Mathlib/Tactic/IntervalCases.lean b/Mathlib/Tactic/IntervalCases.lean index 621a718ffea2c..52169b6406e4c 100644 --- a/Mathlib/Tactic/IntervalCases.lean +++ b/Mathlib/Tactic/IntervalCases.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Mario Carneiro +Authors: Kim Morrison, Mario Carneiro -/ import Mathlib.Tactic.NormNum import Mathlib.Tactic.FinCases diff --git a/Mathlib/Tactic/NoncommRing.lean b/Mathlib/Tactic/NoncommRing.lean index 46fd98f60bca4..f7c338b2c3b82 100644 --- a/Mathlib/Tactic/NoncommRing.lean +++ b/Mathlib/Tactic/NoncommRing.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jireh Loreaux, Scott Morrison, Oliver Nash +Authors: Jireh Loreaux, Kim Morrison, Oliver Nash -/ import Mathlib.Algebra.Group.Action.Defs import Mathlib.Tactic.Abel diff --git a/Mathlib/Tactic/Propose.lean b/Mathlib/Tactic/Propose.lean index 9ca99b07d8d03..4169210c6c5ce 100644 --- a/Mathlib/Tactic/Propose.lean +++ b/Mathlib/Tactic/Propose.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Lean.Meta.Tactic.TryThis import Lean.Meta.Tactic.SolveByElim diff --git a/Mathlib/Tactic/Relation/Symm.lean b/Mathlib/Tactic/Relation/Symm.lean index 6057927cfb8b5..8d33854268714 100644 --- a/Mathlib/Tactic/Relation/Symm.lean +++ b/Mathlib/Tactic/Relation/Symm.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Meta.Tactic.Symm diff --git a/Mathlib/Tactic/RewriteSearch.lean b/Mathlib/Tactic/RewriteSearch.lean index befd4ab7e0ee1..f91c389946783 100644 --- a/Mathlib/Tactic/RewriteSearch.lean +++ b/Mathlib/Tactic/RewriteSearch.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Lean FRO, LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Lean.Meta.Tactic.Rewrites import Mathlib.Algebra.Order.Group.Nat diff --git a/Mathlib/Tactic/Says.lean b/Mathlib/Tactic/Says.lean index 72b195ef15967..87f93ae495ba1 100644 --- a/Mathlib/Tactic/Says.lean +++ b/Mathlib/Tactic/Says.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Kim Liesinger. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Liesinger +Authors: Kim Morrison -/ import Mathlib.Init import Batteries.Data.String.Basic diff --git a/Mathlib/Tactic/SlimCheck.lean b/Mathlib/Tactic/SlimCheck.lean index 66c0e52fbbb68..d30b24c1f4eb5 100644 --- a/Mathlib/Tactic/SlimCheck.lean +++ b/Mathlib/Tactic/SlimCheck.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Simon Hudon, Scott Morrison +Authors: Simon Hudon, Kim Morrison -/ import Mathlib.Testing.SlimCheck.Testable diff --git a/Mathlib/Tactic/SuccessIfFailWithMsg.lean b/Mathlib/Tactic/SuccessIfFailWithMsg.lean index 9d80c1c15e17a..70bb4e7e8468d 100644 --- a/Mathlib/Tactic/SuccessIfFailWithMsg.lean +++ b/Mathlib/Tactic/SuccessIfFailWithMsg.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Simon Hudon, Sébastien Gouëzel, Scott Morrison, Thomas Murrills +Authors: Mario Carneiro, Simon Hudon, Sébastien Gouëzel, Kim Morrison, Thomas Murrills -/ import Mathlib.Init import Lean diff --git a/Mathlib/Topology/Algebra/Algebra.lean b/Mathlib/Topology/Algebra/Algebra.lean index bcc728324280b..367ba0a65e42e 100644 --- a/Mathlib/Topology/Algebra/Algebra.lean +++ b/Mathlib/Topology/Algebra/Algebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Antoine Chambert-Loir, María Inés de Frutos-Fernández +Authors: Kim Morrison, Antoine Chambert-Loir, María Inés de Frutos-Fernández -/ import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Topology.Algebra.Module.Basic diff --git a/Mathlib/Topology/Algebra/Algebra/Rat.lean b/Mathlib/Topology/Algebra/Algebra/Rat.lean index d63250277c31e..212c43adc23f5 100644 --- a/Mathlib/Topology/Algebra/Algebra/Rat.lean +++ b/Mathlib/Topology/Algebra/Algebra/Rat.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Algebra.Rat import Mathlib.Topology.Algebra.Monoid diff --git a/Mathlib/Topology/Algebra/Field.lean b/Mathlib/Topology/Algebra/Field.lean index 712e7a66bee25..0b7ccfdded133 100644 --- a/Mathlib/Topology/Algebra/Field.lean +++ b/Mathlib/Topology/Algebra/Field.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2021 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison +Authors: Patrick Massot, Kim Morrison -/ import Mathlib.Algebra.Field.Subfield import Mathlib.Algebra.GroupWithZero.Divisibility diff --git a/Mathlib/Topology/Category/TopCat/Adjunctions.lean b/Mathlib/Topology/Category/TopCat/Adjunctions.lean index 9b3820db940f7..e42823dc49ca5 100644 --- a/Mathlib/Topology/Category/TopCat/Adjunctions.lean +++ b/Mathlib/Topology/Category/TopCat/Adjunctions.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Mario Carneiro -/ diff --git a/Mathlib/Topology/Category/TopCat/Basic.lean b/Mathlib/Topology/Category/TopCat/Basic.lean index 5d001338b22c2..40459bf75dc71 100644 --- a/Mathlib/Topology/Category/TopCat/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison, Mario Carneiro +Authors: Patrick Massot, Kim Morrison, Mario Carneiro -/ import Mathlib.CategoryTheory.ConcreteCategory.BundledHom import Mathlib.Topology.ContinuousFunction.Basic diff --git a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean index 2c9ab0122ae91..3fcf13740229c 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang +Authors: Patrick Massot, Kim Morrison, Mario Carneiro, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.Basic import Mathlib.CategoryTheory.Limits.Types diff --git a/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean b/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean index a6ef38a679ede..7350fd1934dc2 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang +Authors: Patrick Massot, Kim Morrison, Mario Carneiro, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.Limits.Basic import Mathlib.CategoryTheory.Filtered.Basic diff --git a/Mathlib/Topology/Category/TopCat/Limits/Products.lean b/Mathlib/Topology/Category/TopCat/Limits/Products.lean index 20ee2f8395a8d..12a0b862fc298 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Products.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Products.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang +Authors: Patrick Massot, Kim Morrison, Mario Carneiro, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.EpiMono import Mathlib.Topology.Category.TopCat.Limits.Basic diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index 80e0708f53c5a..7701c3fb0e265 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2017 Scott Morrison. All rights reserved. +Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang +Authors: Patrick Massot, Kim Morrison, Mario Carneiro, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.Limits.Products diff --git a/Mathlib/Topology/Category/TopCat/OpenNhds.lean b/Mathlib/Topology/Category/TopCat/OpenNhds.lean index 4e61f6003d869..d9325ee6922be 100644 --- a/Mathlib/Topology/Category/TopCat/OpenNhds.lean +++ b/Mathlib/Topology/Category/TopCat/OpenNhds.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Category.TopCat.Opens import Mathlib.Data.Set.Subsingleton diff --git a/Mathlib/Topology/Category/TopCat/Opens.lean b/Mathlib/Topology/Category/TopCat/Opens.lean index 2fef8bad29adf..988c19dba4faa 100644 --- a/Mathlib/Topology/Category/TopCat/Opens.lean +++ b/Mathlib/Topology/Category/TopCat/Opens.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.EqToHom diff --git a/Mathlib/Topology/Category/TopCommRingCat.lean b/Mathlib/Topology/Category/TopCommRingCat.lean index 153f2b41ff795..b6734c03f35c7 100644 --- a/Mathlib/Topology/Category/TopCommRingCat.lean +++ b/Mathlib/Topology/Category/TopCommRingCat.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Ring.Basic import Mathlib.Topology.Category.TopCat.Basic diff --git a/Mathlib/Topology/Category/UniformSpace.lean b/Mathlib/Topology/Category/UniformSpace.lean index ebeee9ca6766e..0b3083f80e4e6 100644 --- a/Mathlib/Topology/Category/UniformSpace.lean +++ b/Mathlib/Topology/Category/UniformSpace.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Reid Barton, Patrick Massot, Scott Morrison +Authors: Reid Barton, Patrick Massot, Kim Morrison -/ import Mathlib.CategoryTheory.Adjunction.Reflective import Mathlib.CategoryTheory.ConcreteCategory.UnbundledHom diff --git a/Mathlib/Topology/ContinuousFunction/Algebra.lean b/Mathlib/Topology/ContinuousFunction/Algebra.lean index c3143c043f066..f355d40dd16c6 100644 --- a/Mathlib/Topology/ContinuousFunction/Algebra.lean +++ b/Mathlib/Topology/ContinuousFunction/Algebra.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Nicolò Cavalleri +Authors: Kim Morrison, Nicolò Cavalleri -/ import Mathlib.Algebra.Algebra.Pi import Mathlib.Algebra.Order.Group.Lattice diff --git a/Mathlib/Topology/ContinuousFunction/Compact.lean b/Mathlib/Topology/ContinuousFunction/Compact.lean index 114876977a04d..50b42bb56fb90 100644 --- a/Mathlib/Topology/ContinuousFunction/Compact.lean +++ b/Mathlib/Topology/ContinuousFunction/Compact.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.ContinuousFunction.Bounded import Mathlib.Topology.UniformSpace.Compact diff --git a/Mathlib/Topology/ContinuousFunction/Ordered.lean b/Mathlib/Topology/ContinuousFunction/Ordered.lean index 7e46c520e70b6..383451ecd6565 100644 --- a/Mathlib/Topology/ContinuousFunction/Ordered.lean +++ b/Mathlib/Topology/ContinuousFunction/Ordered.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Shing Tak Lam +Authors: Kim Morrison, Shing Tak Lam -/ import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Topology.Order.Lattice diff --git a/Mathlib/Topology/ContinuousFunction/Polynomial.lean b/Mathlib/Topology/ContinuousFunction/Polynomial.lean index 3fd434d44adc3..5e3cd45660fa2 100644 --- a/Mathlib/Topology/ContinuousFunction/Polynomial.lean +++ b/Mathlib/Topology/ContinuousFunction/Polynomial.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Algebra.Polynomial import Mathlib.Topology.ContinuousFunction.Algebra diff --git a/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean b/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean index 57b51d1724771..75dd242760f15 100644 --- a/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean +++ b/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Heather Macbeth +Authors: Kim Morrison, Heather Macbeth -/ import Mathlib.Algebra.Algebra.Subalgebra.Unitization import Mathlib.Analysis.RCLike.Basic diff --git a/Mathlib/Topology/ContinuousFunction/Weierstrass.lean b/Mathlib/Topology/ContinuousFunction/Weierstrass.lean index 90730fc0e1d83..fbfdd66fb2023 100644 --- a/Mathlib/Topology/ContinuousFunction/Weierstrass.lean +++ b/Mathlib/Topology/ContinuousFunction/Weierstrass.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Analysis.SpecialFunctions.Bernstein import Mathlib.Topology.Algebra.Algebra diff --git a/Mathlib/Topology/Sheaves/Forget.lean b/Mathlib/Topology/Sheaves/Forget.lean index 6783eda87f149..f92a32f660346 100644 --- a/Mathlib/Topology/Sheaves/Forget.lean +++ b/Mathlib/Topology/Sheaves/Forget.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Category.Ring.Limits import Mathlib.Topology.Sheaves.Sheaf diff --git a/Mathlib/Topology/Sheaves/Limits.lean b/Mathlib/Topology/Sheaves/Limits.lean index 7309973470775..af880e9d7ae36 100644 --- a/Mathlib/Topology/Sheaves/Limits.lean +++ b/Mathlib/Topology/Sheaves/Limits.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Sheaves.Sheaf import Mathlib.CategoryTheory.Sites.Limits diff --git a/Mathlib/Topology/Sheaves/LocalPredicate.lean b/Mathlib/Topology/Sheaves/LocalPredicate.lean index 2c3ef5febbef1..c27257e4a8618 100644 --- a/Mathlib/Topology/Sheaves/LocalPredicate.lean +++ b/Mathlib/Topology/Sheaves/LocalPredicate.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison, Adam Topaz +Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.Topology.Sheaves.SheafOfFunctions import Mathlib.Topology.Sheaves.Stalks diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index 1045f3e96ce28..c3fda4efb382e 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2018 Scott Morrison. All rights reserved. +Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Mario Carneiro, Reid Barton, Andrew Yang +Authors: Kim Morrison, Mario Carneiro, Reid Barton, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.Opens import Mathlib.CategoryTheory.Adjunction.Unique diff --git a/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean b/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean index 24ed94958851d..23061bd8b782f 100644 --- a/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean +++ b/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Yoneda import Mathlib.Topology.Sheaves.Presheaf diff --git a/Mathlib/Topology/Sheaves/Sheaf.lean b/Mathlib/Topology/Sheaves/Sheaf.lean index c13307d1eeab1..6345a02e5c3c7 100644 --- a/Mathlib/Topology/Sheaves/Sheaf.lean +++ b/Mathlib/Topology/Sheaves/Sheaf.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Sheaves.Presheaf import Mathlib.CategoryTheory.Sites.Sheaf diff --git a/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean b/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean index 25fd50eb55023..34b950b76fec8 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.Equalizers import Mathlib.CategoryTheory.Limits.Shapes.Products diff --git a/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean b/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean index ace2385ed29bd..318e4ad961054 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Sheaves.SheafCondition.Sites diff --git a/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean b/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean index 7dcee720fc546..9677da6bdf32e 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Sheaves.SheafCondition.OpensLeCover import Mathlib.CategoryTheory.Limits.Final diff --git a/Mathlib/Topology/Sheaves/SheafOfFunctions.lean b/Mathlib/Topology/Sheaves/SheafOfFunctions.lean index 4aea0cf255c09..e2c75974e54e3 100644 --- a/Mathlib/Topology/Sheaves/SheafOfFunctions.lean +++ b/Mathlib/Topology/Sheaves/SheafOfFunctions.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Scott Morrison +Authors: Johan Commelin, Kim Morrison -/ import Mathlib.Topology.Sheaves.PresheafOfFunctions import Mathlib.Topology.Sheaves.SheafCondition.UniqueGluing diff --git a/Mathlib/Topology/Sheaves/Sheafify.lean b/Mathlib/Topology/Sheaves/Sheafify.lean index 14b6e48ce063c..423700fb192c9 100644 --- a/Mathlib/Topology/Sheaves/Sheafify.lean +++ b/Mathlib/Topology/Sheaves/Sheafify.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2020 Scott Morrison. All rights reserved. +Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Topology.Sheaves.LocalPredicate import Mathlib.Topology.Sheaves.Stalks diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index 36574cf04a2b3..da3cfda14b8b4 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Justus Springer +Authors: Kim Morrison, Justus Springer -/ import Mathlib.Topology.Category.TopCat.OpenNhds import Mathlib.Topology.Sheaves.Presheaf diff --git a/Mathlib/Topology/UnitInterval.lean b/Mathlib/Topology/UnitInterval.lean index 52a1b15721742..69b4eada244b4 100644 --- a/Mathlib/Topology/UnitInterval.lean +++ b/Mathlib/Topology/UnitInterval.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison +Authors: Patrick Massot, Kim Morrison -/ import Mathlib.Algebra.Order.Interval.Set.Instances import Mathlib.Order.Interval.Set.ProjIcc diff --git a/Mathlib/Util/AddRelatedDecl.lean b/Mathlib/Util/AddRelatedDecl.lean index f415c55828e22..ecea6a5c315b8 100644 --- a/Mathlib/Util/AddRelatedDecl.lean +++ b/Mathlib/Util/AddRelatedDecl.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Floris van Doorn +Authors: Kim Morrison, Floris van Doorn -/ import Mathlib.Init import Lean.Elab.DeclarationRange diff --git a/Mathlib/Util/AssertExists.lean b/Mathlib/Util/AssertExists.lean index 2995ff633ca25..386f6f122afc9 100644 --- a/Mathlib/Util/AssertExists.lean +++ b/Mathlib/Util/AssertExists.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Scott Morrison +Authors: Patrick Massot, Kim Morrison -/ import Mathlib.Init import Lean.Elab.Command diff --git a/Mathlib/Util/CountHeartbeats.lean b/Mathlib/Util/CountHeartbeats.lean index 795aac8b29aa1..3b30d85e1aa29 100644 --- a/Mathlib/Util/CountHeartbeats.lean +++ b/Mathlib/Util/CountHeartbeats.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Util.Heartbeats diff --git a/Mathlib/Util/LongNames.lean b/Mathlib/Util/LongNames.lean index 43e6789218bc4..081b0dfe749d6 100644 --- a/Mathlib/Util/LongNames.lean +++ b/Mathlib/Util/LongNames.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Lean.Name import Mathlib.Lean.Expr.Basic diff --git a/Mathlib/Util/Qq.lean b/Mathlib/Util/Qq.lean index af1dbac4f7ad8..5232470c0d692 100644 --- a/Mathlib/Util/Qq.lean +++ b/Mathlib/Util/Qq.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2023 Scott Morrison. All rights reserved. +Copyright (c) 2023 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison, Alex J. Best +Authors: Kim Morrison, Alex J. Best -/ import Mathlib.Init import Qq diff --git a/Mathlib/Util/SynthesizeUsing.lean b/Mathlib/Util/SynthesizeUsing.lean index a9979d22f051f..6e65203680e84 100644 --- a/Mathlib/Util/SynthesizeUsing.lean +++ b/Mathlib/Util/SynthesizeUsing.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2022 Scott Morrison. All rights reserved. +Copyright (c) 2022 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Init import Lean.Elab.Tactic.Basic diff --git a/docs/100.yaml b/docs/100.yaml index 733af55cb0669..b1fb269096866 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -183,7 +183,7 @@ 49: title : The Cayley-Hamilton Theorem decl : Matrix.aeval_self_charpoly - author : Scott Morrison + author : Kim Morrison 50: title : The Number of Platonic Solids 51: @@ -345,7 +345,7 @@ title : Morley’s Theorem 85: title : Divisibility by 3 Rule - author : Scott Morrison + author : Kim Morrison decls : - Nat.three_dvd_iff 86: diff --git a/test/interval_cases.lean b/test/interval_cases.lean index bf08cde4046dd..02cbfc56c324a 100644 --- a/test/interval_cases.lean +++ b/test/interval_cases.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2019 Scott Morrison. All rights reserved. +Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Tactic.IntervalCases diff --git a/test/solve_by_elim/basic.lean b/test/solve_by_elim/basic.lean index e543527641969..ce407f3089f28 100644 --- a/test/solve_by_elim/basic.lean +++ b/test/solve_by_elim/basic.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Lean.Meta.Tactic.SolveByElim import Mathlib.Tactic.Constructor diff --git a/test/solve_by_elim/instances.lean b/test/solve_by_elim/instances.lean index f92a260c4d24d..6c060e07c9f27 100644 --- a/test/solve_by_elim/instances.lean +++ b/test/solve_by_elim/instances.lean @@ -1,7 +1,7 @@ /- -Copyright (c) 2021 Scott Morrison. All rights reserved. +Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison +Authors: Kim Morrison -/ import Mathlib.Algebra.Order.GroupWithZero.Synonym import Mathlib.Algebra.Order.Ring.Nat From 4d111f35fcac236a98ac0364aad700d5b2fc8d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 24 Sep 2024 07:14:48 +0000 Subject: [PATCH 120/170] feat(Order/WellFounded): `StrictMono.not_bddAbove_range` (#16960) A strict monotonic function in an unbounded well-order has an unbounded range. --- Mathlib/Order/SuccPred/Archimedean.lean | 31 ++++++++++++++++++------- Mathlib/Order/WellFounded.lean | 11 +++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Mathlib/Order/SuccPred/Archimedean.lean b/Mathlib/Order/SuccPred/Archimedean.lean index 388fa53c6f03d..6a225c713afdc 100644 --- a/Mathlib/Order/SuccPred/Archimedean.lean +++ b/Mathlib/Order/SuccPred/Archimedean.lean @@ -138,8 +138,8 @@ end LinearOrder section bdd_range variable [Preorder α] [Nonempty α] [Preorder β] {f : α → β} -lemma StrictMono.not_bddAbove_range [NoMaxOrder α] [SuccOrder β] [IsSuccArchimedean β] - (hf : StrictMono f) : ¬ BddAbove (Set.range f) := by +lemma StrictMono.not_bddAbove_range_of_isSuccArchimedean [NoMaxOrder α] [SuccOrder β] + [IsSuccArchimedean β] (hf : StrictMono f) : ¬ BddAbove (Set.range f) := by rintro ⟨m, hm⟩ have hm' : ∀ a, f a ≤ m := fun a ↦ hm <| Set.mem_range_self _ obtain ⟨a₀⟩ := ‹Nonempty α› @@ -152,14 +152,29 @@ lemma StrictMono.not_bddAbove_range [NoMaxOrder α] [SuccOrder β] [IsSuccArchim rintro b _ ⟨a, hba⟩ exact (h a).imp (fun a' ↦ (succ_le_of_lt hba).trans_lt) -lemma StrictMono.not_bddBelow_range [NoMinOrder α] [PredOrder β] [IsPredArchimedean β] - (hf : StrictMono f) : ¬ BddBelow (Set.range f) := hf.dual.not_bddAbove_range +@[deprecated StrictMono.not_bddAbove_range_of_isSuccArchimedean (since := "2024-09-21")] +alias StrictMono.not_bddAbove_range := StrictMono.not_bddAbove_range_of_isSuccArchimedean -lemma StrictAnti.not_bddAbove_range [NoMinOrder α] [SuccOrder β] [IsSuccArchimedean β] - (hf : StrictAnti f) : ¬ BddAbove (Set.range f) := hf.dual_right.not_bddBelow_range +lemma StrictMono.not_bddBelow_range_of_isPredArchimedean [NoMinOrder α] [PredOrder β] + [IsPredArchimedean β] (hf : StrictMono f) : ¬ BddBelow (Set.range f) := + hf.dual.not_bddAbove_range_of_isSuccArchimedean -lemma StrictAnti.not_bddBelow_range [NoMaxOrder α] [PredOrder β] [IsPredArchimedean β] - (hf : StrictAnti f) : ¬ BddBelow (Set.range f) := hf.dual_right.not_bddAbove_range +@[deprecated StrictMono.not_bddBelow_range_of_isPredArchimedean (since := "2024-09-21")] +alias StrictMono.not_bddBelow_range := StrictMono.not_bddBelow_range_of_isPredArchimedean + +lemma StrictAnti.not_bddBelow_range_of_isSuccArchimedean [NoMinOrder α] [SuccOrder β] + [IsSuccArchimedean β] (hf : StrictAnti f) : ¬ BddAbove (Set.range f) := + hf.dual_right.not_bddBelow_range_of_isPredArchimedean + +@[deprecated StrictAnti.not_bddBelow_range_of_isSuccArchimedean (since := "2024-09-21")] +alias StrictAnti.not_bddAbove_range := StrictAnti.not_bddBelow_range_of_isSuccArchimedean + +lemma StrictAnti.not_bddBelow_range_of_isPredArchimedean [NoMaxOrder α] [PredOrder β] + [IsPredArchimedean β] (hf : StrictAnti f) : ¬ BddBelow (Set.range f) := + hf.dual_right.not_bddAbove_range_of_isSuccArchimedean + +@[deprecated StrictAnti.not_bddBelow_range_of_isPredArchimedean (since := "2024-09-21")] +alias StrictAnti.not_bddBelow_range := StrictAnti.not_bddBelow_range_of_isPredArchimedean end bdd_range diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index a397938c55124..613d28890f078 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Mario Carneiro -/ import Mathlib.Data.Set.Function +import Mathlib.Order.Bounds.Basic /-! # Well-founded relations @@ -188,6 +189,16 @@ theorem WellFounded.self_le_of_strictMono (h : WellFounded ((· < ·) : β → have h₂ := h.min_mem _ h₁ exact h.not_lt_min _ h₁ (hf h₂) h₂ +theorem StrictMono.not_bddAbove_range_of_wellFoundedLT {f : β → β} [WellFoundedLT β] [NoMaxOrder β] + (hf : StrictMono f) : ¬ BddAbove (Set.range f) := by + rintro ⟨a, ha⟩ + obtain ⟨b, hb⟩ := exists_gt a + exact ((hf.le_apply.trans_lt (hf hb)).trans_le <| ha (Set.mem_range_self _)).false + +theorem StrictMono.not_bddBelow_range_of_wellFoundedGT {f : β → β} [WellFoundedGT β] [NoMinOrder β] + (hf : StrictMono f) : ¬ BddBelow (Set.range f) := + hf.dual.not_bddAbove_range_of_wellFoundedLT + end LinearOrder namespace Function From ac554e73e90ab4ffad26e04fdc27304ffe8500ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 24 Sep 2024 07:14:49 +0000 Subject: [PATCH 121/170] =?UTF-8?q?chore(Order/InitialSeg):=20`init`=20?= =?UTF-8?q?=E2=86=92=20`mem=5Frange=5Fof=5Frel`=20(#16994)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We rename some `init` theorems that had very vague names beforehand, and we state them in terms of (the definitionally equal) `Set.range`. --- Mathlib/Order/InitialSeg.lean | 42 +++++++++++++++-------- Mathlib/SetTheory/Ordinal/Arithmetic.lean | 3 +- Mathlib/SetTheory/Ordinal/Basic.lean | 4 +-- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/Mathlib/Order/InitialSeg.lean b/Mathlib/Order/InitialSeg.lean index 2ae4fcd5010cc..83ab64a3e5d24 100644 --- a/Mathlib/Order/InitialSeg.lean +++ b/Mathlib/Order/InitialSeg.lean @@ -48,7 +48,7 @@ embedding whose range is an initial segment. That is, whenever `b < f a` in `β` range of `f`. -/ structure InitialSeg {α β : Type*} (r : α → α → Prop) (s : β → β → Prop) extends r ↪r s where /-- The order embedding is an initial segment -/ - init' : ∀ a b, s b (toRelEmbedding a) → ∃ a', toRelEmbedding a' = b + mem_range_of_rel' : ∀ a b, s b (toRelEmbedding a) → b ∈ Set.range toRelEmbedding -- Porting note: Deleted `scoped[InitialSeg]` /-- If `r` is a relation on `α` and `s` in a relation on `β`, then `f : r ≼i s` is an order @@ -78,18 +78,24 @@ instance : EmbeddingLike (r ≼i s) α β where theorem coe_coe_fn (f : r ≼i s) : ((f : r ↪r s) : α → β) = f := rfl -theorem init (f : r ≼i s) {a : α} {b : β} : s b (f a) → ∃ a', f a' = b := - f.init' _ _ +theorem mem_range_of_rel (f : r ≼i s) {a : α} {b : β} : s b (f a) → b ∈ Set.range f := + f.mem_range_of_rel' _ _ + +@[deprecated mem_range_of_rel (since := "2024-09-21")] +alias init := mem_range_of_rel theorem map_rel_iff {a b : α} (f : r ≼i s) : s (f a) (f b) ↔ r a b := f.map_rel_iff' -theorem init_iff (f : r ≼i s) {a : α} {b : β} : s b (f a) ↔ ∃ a', f a' = b ∧ r a' a := +theorem exists_eq_iff_rel (f : r ≼i s) {a : α} {b : β} : s b (f a) ↔ ∃ a', f a' = b ∧ r a' a := ⟨fun h => by - rcases f.init h with ⟨a', rfl⟩ + rcases f.mem_range_of_rel h with ⟨a', rfl⟩ exact ⟨a', rfl, f.map_rel_iff.1 h⟩, fun ⟨a', e, h⟩ => e ▸ f.map_rel_iff.2 h⟩ +@[deprecated exists_eq_iff_rel (since := "2024-09-21")] +alias init_iff := exists_eq_iff_rel + /-- An order isomorphism is an initial segment -/ def ofIso (f : r ≃r s) : r ≼i s := ⟨f, fun _ b _ => ⟨f.symm b, RelIso.apply_symm_apply f _⟩⟩ @@ -124,7 +130,7 @@ instance subsingleton_of_trichotomous_of_irrefl [IsTrichotomous β s] [IsIrrefl ext a refine IsWellFounded.induction r a fun b IH => extensional_of_trichotomous_of_irrefl s fun x => ?_ - rw [f.init_iff, g.init_iff] + rw [f.exists_eq_iff_rel, g.exists_eq_iff_rel] exact exists_congr fun x => and_congr_left fun hx => IH _ hx ▸ Iff.rfl⟩ instance [IsWellOrder β s] : Subsingleton (r ≼i s) := @@ -161,12 +167,12 @@ theorem eq_or_principal [IsWellOrder β s] (f : r ≼i s) : ⟨IH _, fun ⟨a, e⟩ => by rw [← e] exact (trichotomous _ _).resolve_right - (not_or_intro (hn a) fun hl => not_exists.2 hn (f.init hl))⟩⟩ + (not_or_intro (hn a) fun hl => not_exists.2 hn (f.mem_range_of_rel hl))⟩⟩ /-- Restrict the codomain of an initial segment -/ def codRestrict (p : Set β) (f : r ≼i s) (H : ∀ a, f a ∈ p) : r ≼i Subrel s p := ⟨RelEmbedding.codRestrict p f H, fun a ⟨b, m⟩ h => - let ⟨a', e⟩ := f.init h + let ⟨a', e⟩ := f.mem_range_of_rel h ⟨a', by subst e; rfl⟩⟩ @[simp] @@ -189,7 +195,7 @@ theorem leAdd_apply (r : α → α → Prop) (s : β → β → Prop) (a) : leAd protected theorem acc (f : r ≼i s) (a : α) : Acc r a ↔ Acc s (f a) := ⟨by refine fun h => Acc.recOn h fun a _ ha => Acc.intro _ fun b hb => ?_ - obtain ⟨a', rfl⟩ := f.init hb + obtain ⟨a', rfl⟩ := f.mem_range_of_rel hb exact ha _ (f.map_rel_iff.mp hb), f.toRelEmbedding.acc a⟩ end InitialSeg @@ -237,18 +243,26 @@ theorem down (f : r ≺i s) : ∀ {b : β}, s b f.top ↔ ∃ a, f a = b := theorem lt_top (f : r ≺i s) (a : α) : s (f a) f.top := f.down.2 ⟨_, rfl⟩ -theorem init [IsTrans β s] (f : r ≺i s) {a : α} {b : β} (h : s b (f a)) : ∃ a', f a' = b := +theorem mem_range_of_rel [IsTrans β s] (f : r ≺i s) {a : α} {b : β} (h : s b (f a)) : + b ∈ Set.range f := f.down.1 <| _root_.trans h <| f.lt_top _ +@[deprecated mem_range_of_rel (since := "2024-09-21")] +alias init := mem_range_of_rel + /-- A principal segment is in particular an initial segment. -/ instance hasCoeInitialSeg [IsTrans β s] : Coe (r ≺i s) (r ≼i s) := - ⟨fun f => ⟨f.toRelEmbedding, fun _ _ => f.init⟩⟩ + ⟨fun f => ⟨f.toRelEmbedding, fun _ _ => f.mem_range_of_rel⟩⟩ theorem coe_coe_fn' [IsTrans β s] (f : r ≺i s) : ((f : r ≼i s) : α → β) = f := rfl -theorem init_iff [IsTrans β s] (f : r ≺i s) {a : α} {b : β} : s b (f a) ↔ ∃ a', f a' = b ∧ r a' a := - @InitialSeg.init_iff α β r s f a b +theorem exists_eq_iff_rel [IsTrans β s] (f : r ≺i s) {a : α} {b : β} : + s b (f a) ↔ ∃ a', f a' = b ∧ r a' a := + @InitialSeg.exists_eq_iff_rel α β r s f a b + +@[deprecated exists_eq_iff_rel (since := "2024-09-21")] +alias init_iff := exists_eq_iff_rel /-- A principal segment is the same as a non-surjective initial segment. -/ noncomputable def _root_.InitialSeg.toPrincipalSeg [IsWellOrder β s] (f : r ≼i s) @@ -272,7 +286,7 @@ instance (r : α → α → Prop) [IsWellOrder α r] : IsEmpty (r ≺i r) := /-- Composition of a principal segment with an initial segment, as a principal segment -/ def ltLe (f : r ≺i s) (g : s ≼i t) : r ≺i t := ⟨@RelEmbedding.trans _ _ _ r s t f g, g f.top, fun a => by - simp only [g.init_iff, PrincipalSeg.down, exists_and_left.symm, exists_swap, + simp only [g.exists_eq_iff_rel, PrincipalSeg.down, exists_and_left.symm, exists_swap, RelEmbedding.trans_apply, exists_eq_right', InitialSeg.coe_coe_fn]⟩ @[simp] diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 3fb5355737b96..8beea98d87249 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -104,7 +104,8 @@ instance add_contravariantClass_le : ContravariantClass Ordinal.{u} Ordinal.{u} simpa only [Sum.lex_inr_inr, fr, InitialSeg.coe_coe_fn, Embedding.coeFn_mk] using @RelEmbedding.map_rel_iff _ _ _ _ f.toRelEmbedding (Sum.inr a) (Sum.inr b)⟩, fun a b H => by - rcases f.init (by rw [fr] <;> exact Sum.lex_inr_inr.2 H) with ⟨a' | a', h⟩ + rcases f.mem_range_of_rel (by rw [fr] <;> exact Sum.lex_inr_inr.2 H) with + ⟨a' | a', h⟩ · rw [fl] at h cases h · rw [fr] at h diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 0ebca27c90b0b..d9a0cb4a39c91 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -392,7 +392,7 @@ theorem typein_apply {α β} {r : α → α → Prop} {s : β → β → Prop} [ (RelEmbedding.codRestrict _ ((Subrel.relEmbedding _ _).trans f) fun ⟨x, h⟩ => by rw [RelEmbedding.trans_apply]; exact f.toRelEmbedding.map_rel_iff.2 h) fun ⟨y, h⟩ => by - rcases f.init h with ⟨a, rfl⟩ + rcases f.mem_range_of_rel h with ⟨a, rfl⟩ exact ⟨⟨a, f.toRelEmbedding.map_rel_iff.1 h⟩, Subtype.eq <| RelEmbedding.trans_apply _ _ _⟩⟩ @@ -862,7 +862,7 @@ private theorem succ_le_iff' {a b : Ordinal} : a + 1 ≤ b ↔ a < b := · exact False.elim ∘ Sum.lex_inr_inr.1 · rcases a with (a | _) · intro h - have := @PrincipalSeg.init _ _ _ _ _ ⟨f, t, hf⟩ _ _ h + have := @PrincipalSeg.mem_range_of_rel _ _ _ _ _ ⟨f, t, hf⟩ _ _ h cases' this with w h exact ⟨Sum.inl w, h⟩ · intro h From 18506a87c21f32c822da9818ec4eb2ae433eb03d Mon Sep 17 00:00:00 2001 From: Etienne Date: Tue, 24 Sep 2024 07:14:50 +0000 Subject: [PATCH 122/170] doc: typo in `properVAdd_iff_continuousVadd_ultrafilter_tendsto` (#17008) Just a typo in the doc. --- Mathlib/Topology/Algebra/ProperAction.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Topology/Algebra/ProperAction.lean b/Mathlib/Topology/Algebra/ProperAction.lean index 2c645d7ab198d..cd13f848a2f41 100644 --- a/Mathlib/Topology/Algebra/ProperAction.lean +++ b/Mathlib/Topology/Algebra/ProperAction.lean @@ -86,7 +86,7 @@ instance (priority := 100) ProperSMul.toContinuousSMul [ProperSMul G X] : Contin /-- A group `G` acts properly on a topological space `X` if and only if for all ultrafilters `𝒰` on `X × G`, if `𝒰` converges to `(x₁, x₂)` along the map `(g, x) ↦ (g • x, x)`, then there exists `g : G` such that `g • x₂ = x₁` and `𝒰.fst` converges to `g`. -/ -@[to_additive "A group acts `G` properly on a topological space `X` if and only if +@[to_additive "A group `G` acts properly on a topological space `X` if and only if for all ultrafilters `𝒰` on `X`, if `𝒰` converges to `(x₁, x₂)` along the map `(g, x) ↦ (g • x, x)`, then there exists `g : G` such that `g • x₂ = x₁` and `𝒰.fst` converges to `g`."] From c15e46e9bd6a62f3d9187d1b433ceefd9bea4749 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 24 Sep 2024 07:14:52 +0000 Subject: [PATCH 123/170] chore(Monoid/Unbundled/Pow): cleanup (#17013) --- .../Algebra/Order/Monoid/Unbundled/Pow.lean | 156 +++++++++--------- 1 file changed, 75 insertions(+), 81 deletions(-) diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean index 877d5f5f47c07..11972efe4bd7d 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean @@ -24,96 +24,100 @@ section Preorder variable [Preorder M] -section Left +namespace Left -variable [CovariantClass M M (· * ·) (· ≤ ·)] {x : M} +variable [CovariantClass M M (· * ·) (· ≤ ·)] {a b : M} -@[to_additive (attr := mono, gcongr) nsmul_le_nsmul_right] -theorem pow_le_pow_left' [CovariantClass M M (swap (· * ·)) (· ≤ ·)] {a b : M} (hab : a ≤ b) : - ∀ i : ℕ, a ^ i ≤ b ^ i - | 0 => by simp - | k + 1 => by - rw [pow_succ, pow_succ] - exact mul_le_mul' (pow_le_pow_left' hab k) hab - -@[to_additive nsmul_nonneg] -theorem one_le_pow_of_one_le' {a : M} (H : 1 ≤ a) : ∀ n : ℕ, 1 ≤ a ^ n +@[to_additive Left.nsmul_nonneg] +theorem one_le_pow_of_le (ha : 1 ≤ a) : ∀ n : ℕ, 1 ≤ a ^ n | 0 => by simp | k + 1 => by rw [pow_succ] - exact one_le_mul (one_le_pow_of_one_le' H k) H + exact one_le_mul (one_le_pow_of_le ha k) ha + +@[deprecated (since := "2024-09-21")] alias pow_nonneg := nsmul_nonneg @[to_additive nsmul_nonpos] -theorem pow_le_one' {a : M} (H : a ≤ 1) (n : ℕ) : a ^ n ≤ 1 := - one_le_pow_of_one_le' (M := Mᵒᵈ) H n +theorem pow_le_one_of_le (ha : a ≤ 1) (n : ℕ) : a ^ n ≤ 1 := one_le_pow_of_le (M := Mᵒᵈ) ha n + +@[deprecated (since := "2024-09-21")] alias pow_nonpos := nsmul_nonpos + +@[to_additive nsmul_neg] +theorem pow_lt_one_of_lt {a : M} {n : ℕ} (h : a < 1) (hn : n ≠ 0) : a ^ n < 1 := by + rcases Nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩ + rw [pow_succ'] + exact mul_lt_one_of_lt_of_le h (pow_le_one_of_le h.le _) + +@[deprecated (since := "2024-09-21")] alias pow_neg := nsmul_neg + +end Left + +@[to_additive nsmul_nonneg] alias one_le_pow_of_one_le' := Left.one_le_pow_of_le +@[to_additive nsmul_nonpos] alias pow_le_one' := Left.pow_le_one_of_le +@[to_additive nsmul_neg] alias pow_lt_one' := Left.pow_lt_one_of_lt + +section Left + +variable [CovariantClass M M (· * ·) (· ≤ ·)] {x : M} + +@[to_additive nsmul_left_monotone] +theorem pow_right_monotone {a : M} (ha : 1 ≤ a) : Monotone fun n : ℕ ↦ a ^ n := + monotone_nat_of_le_succ fun n ↦ by rw [pow_succ]; exact le_mul_of_one_le_right' ha @[to_additive (attr := gcongr) nsmul_le_nsmul_left] theorem pow_le_pow_right' {a : M} {n m : ℕ} (ha : 1 ≤ a) (h : n ≤ m) : a ^ n ≤ a ^ m := - let ⟨k, hk⟩ := Nat.le.dest h - calc - a ^ n ≤ a ^ n * a ^ k := le_mul_of_one_le_right' (one_le_pow_of_one_le' ha _) - _ = a ^ m := by rw [← hk, pow_add] + pow_right_monotone ha h @[to_additive nsmul_le_nsmul_left_of_nonpos] theorem pow_le_pow_right_of_le_one' {a : M} {n m : ℕ} (ha : a ≤ 1) (h : n ≤ m) : a ^ m ≤ a ^ n := pow_le_pow_right' (M := Mᵒᵈ) ha h @[to_additive nsmul_pos] -theorem one_lt_pow' {a : M} (ha : 1 < a) {k : ℕ} (hk : k ≠ 0) : 1 < a ^ k := by - rcases Nat.exists_eq_succ_of_ne_zero hk with ⟨l, rfl⟩ - clear hk - induction l with - | zero => rw [pow_succ]; simpa using ha - | succ l IH => rw [pow_succ]; exact one_lt_mul'' IH ha +theorem one_lt_pow' {a : M} (ha : 1 < a) {k : ℕ} (hk : k ≠ 0) : 1 < a ^ k := + pow_lt_one' (M := Mᵒᵈ) ha hk -@[to_additive nsmul_neg] -theorem pow_lt_one' {a : M} (ha : a < 1) {k : ℕ} (hk : k ≠ 0) : a ^ k < 1 := - one_lt_pow' (M := Mᵒᵈ) ha hk +end Left -@[to_additive (attr := gcongr) nsmul_lt_nsmul_left] -theorem pow_lt_pow_right' [CovariantClass M M (· * ·) (· < ·)] {a : M} {n m : ℕ} (ha : 1 < a) - (h : n < m) : a ^ n < a ^ m := by - rcases Nat.le.dest h with ⟨k, rfl⟩; clear h - rw [pow_add, pow_succ, mul_assoc, ← pow_succ'] - exact lt_mul_of_one_lt_right' _ (one_lt_pow' ha k.succ_ne_zero) +section LeftLt -@[to_additive nsmul_left_strictMono] -theorem pow_right_strictMono' [CovariantClass M M (· * ·) (· < ·)] {a : M} (ha : 1 < a) : - StrictMono ((a ^ ·) : ℕ → M) := fun _ _ => pow_lt_pow_right' ha +variable [CovariantClass M M (· * ·) (· < ·)] {a : M} {n m : ℕ} -@[to_additive Left.pow_nonneg] -theorem Left.one_le_pow_of_le (hx : 1 ≤ x) : ∀ {n : ℕ}, 1 ≤ x ^ n - | 0 => (pow_zero x).ge - | n + 1 => by - rw [pow_succ] - exact Left.one_le_mul (Left.one_le_pow_of_le hx) hx +@[to_additive nsmul_left_strictMono] +theorem pow_right_strictMono' (ha : 1 < a) : StrictMono ((a ^ ·) : ℕ → M) := + strictMono_nat_of_lt_succ fun n ↦ by rw [pow_succ]; exact lt_mul_of_one_lt_right' (a ^ n) ha -@[to_additive Left.pow_nonpos] -theorem Left.pow_le_one_of_le (hx : x ≤ 1) : ∀ {n : ℕ}, x ^ n ≤ 1 - | 0 => (pow_zero _).le - | n + 1 => by - rw [pow_succ] - exact Left.mul_le_one (Left.pow_le_one_of_le hx) hx +@[to_additive (attr := gcongr) nsmul_lt_nsmul_left] +theorem pow_lt_pow_right' (ha : 1 < a) (h : n < m) : a ^ n < a ^ m := + pow_right_strictMono' ha h -end Left +end LeftLt section Right variable [CovariantClass M M (swap (· * ·)) (· ≤ ·)] {x : M} -@[to_additive Right.pow_nonneg] +@[to_additive Right.nsmul_nonneg] theorem Right.one_le_pow_of_le (hx : 1 ≤ x) : ∀ {n : ℕ}, 1 ≤ x ^ n | 0 => (pow_zero _).ge | n + 1 => by rw [pow_succ] exact Right.one_le_mul (Right.one_le_pow_of_le hx) hx -@[to_additive Right.pow_nonpos] -theorem Right.pow_le_one_of_le (hx : x ≤ 1) : ∀ {n : ℕ}, x ^ n ≤ 1 - | 0 => (pow_zero _).le - | n + 1 => by - rw [pow_succ] - exact Right.mul_le_one (Right.pow_le_one_of_le hx) hx +@[deprecated (since := "2024-09-21")] alias Right.pow_nonneg := Right.nsmul_nonneg + +@[to_additive Right.nsmul_nonpos] +theorem Right.pow_le_one_of_le (hx : x ≤ 1) {n : ℕ} : x ^ n ≤ 1 := + Right.one_le_pow_of_le (M := Mᵒᵈ) hx + +@[deprecated (since := "2024-09-21")] alias Right.pow_nonpos := Right.nsmul_nonpos + +@[to_additive Right.nsmul_neg] +theorem Right.pow_lt_one_of_lt {n : ℕ} {x : M} (hn : 0 < n) (h : x < 1) : x ^ n < 1 := by + rcases Nat.exists_eq_succ_of_ne_zero hn.ne' with ⟨k, rfl⟩ + rw [pow_succ] + exact mul_lt_one_of_le_of_lt (pow_le_one_of_le h.le) h + +@[deprecated (since := "2024-09-21")] alias Right.pow_neg := Right.nsmul_neg end Right @@ -144,6 +148,13 @@ section CovariantLESwap variable [Preorder β] [CovariantClass M M (· * ·) (· ≤ ·)] [CovariantClass M M (swap (· * ·)) (· ≤ ·)] +@[to_additive (attr := mono, gcongr) nsmul_le_nsmul_right] +theorem pow_le_pow_left' {a b : M} (hab : a ≤ b) : ∀ i : ℕ, a ^ i ≤ b ^ i + | 0 => by simp + | k + 1 => by + rw [pow_succ, pow_succ] + exact mul_le_mul' (pow_le_pow_left' hab k) hab + @[to_additive Monotone.const_nsmul] theorem Monotone.pow_const {f : β → M} (hf : Monotone f) : ∀ n : ℕ, Monotone fun a => f a ^ n | 0 => by simpa using monotone_const @@ -156,24 +167,6 @@ theorem pow_left_mono (n : ℕ) : Monotone fun a : M => a ^ n := monotone_id.pow end CovariantLESwap -@[to_additive Left.pow_neg] -theorem Left.pow_lt_one_of_lt [CovariantClass M M (· * ·) (· < ·)] {n : ℕ} {x : M} (hn : 0 < n) - (h : x < 1) : x ^ n < 1 := - Nat.le_induction ((pow_one _).trans_lt h) - (fun n _ ih => by - rw [pow_succ] - exact mul_lt_one ih h) - _ (Nat.succ_le_iff.2 hn) - -@[to_additive Right.pow_neg] -theorem Right.pow_lt_one_of_lt [CovariantClass M M (swap (· * ·)) (· < ·)] {n : ℕ} {x : M} - (hn : 0 < n) (h : x < 1) : x ^ n < 1 := - Nat.le_induction ((pow_one _).trans_lt h) - (fun n _ ih => by - rw [pow_succ] - exact Right.mul_lt_one ih h) - _ (Nat.succ_le_iff.2 hn) - end Preorder section LinearOrder @@ -206,6 +199,10 @@ theorem pow_eq_one_iff {x : M} {n : ℕ} (hn : n ≠ 0) : x ^ n = 1 ↔ x = 1 := simp only [le_antisymm_iff] rw [pow_le_one_iff hn, one_le_pow_iff hn] +end CovariantLE + +section CovariantLT + variable [CovariantClass M M (· * ·) (· < ·)] {a : M} {m n : ℕ} @[to_additive nsmul_le_nsmul_iff_left] @@ -216,7 +213,7 @@ theorem pow_le_pow_iff_right' (ha : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := theorem pow_lt_pow_iff_right' (ha : 1 < a) : a ^ m < a ^ n ↔ m < n := (pow_right_strictMono' ha).lt_iff_lt -end CovariantLE +end CovariantLT section CovariantLESwap @@ -266,11 +263,8 @@ theorem Left.pow_lt_one_iff [CovariantClass M M (· * ·) (· < ·)] {n : ℕ} { @[to_additive] theorem Right.pow_lt_one_iff [CovariantClass M M (swap (· * ·)) (· < ·)] {n : ℕ} {x : M} (hn : 0 < n) : x ^ n < 1 ↔ x < 1 := - ⟨fun H => - not_le.mp fun k => - haveI := covariantClass_le_of_lt M M (swap (· * ·)) - H.not_le <| Right.one_le_pow_of_le k, - Right.pow_lt_one_of_lt hn⟩ + haveI := covariantClass_le_of_lt M M (swap (· * ·)) + ⟨fun H => not_le.mp fun k => H.not_le <| Right.one_le_pow_of_le k, Right.pow_lt_one_of_lt hn⟩ end LinearOrder From f9a6642793ae66d29f800b7d153fb2af807a18ad Mon Sep 17 00:00:00 2001 From: Etienne Date: Tue, 24 Sep 2024 08:19:35 +0000 Subject: [PATCH 124/170] feat: a property satisfied almost everywhere is satisfied on a dense subset (#17055) A property satisfied almost everywhere is satisfied on a dense subset. --- Mathlib/MeasureTheory/Measure/OpenPos.lean | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Mathlib/MeasureTheory/Measure/OpenPos.lean b/Mathlib/MeasureTheory/Measure/OpenPos.lean index 611930fcce591..086d4961c2a0e 100644 --- a/Mathlib/MeasureTheory/Measure/OpenPos.lean +++ b/Mathlib/MeasureTheory/Measure/OpenPos.lean @@ -100,6 +100,11 @@ theorem _root_.IsClosed.measure_eq_one_iff_eq_univ [OpensMeasurableSpace X] [IsP theorem interior_eq_empty_of_null (hs : μ s = 0) : interior s = ∅ := isOpen_interior.eq_empty_of_measure_zero <| measure_mono_null interior_subset hs +/-- A property satisfied almost everywhere is satisfied on a dense subset. -/ +theorem dense_of_ae {p : X → Prop} (hp : ∀ᵐ x ∂μ, p x) : Dense {x | p x} := by + rw [dense_iff_closure_eq, closure_eq_compl_interior_compl, compl_univ_iff] + exact μ.interior_eq_empty_of_null hp + /-- If two functions are a.e. equal on an open set and are continuous on this set, then they are equal on this set. -/ theorem eqOn_open_of_ae_eq {f g : X → Y} (h : f =ᵐ[μ.restrict U] g) (hU : IsOpen U) From 2d315a5207bed17ab2ea823c3ec8a60728012a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 24 Sep 2024 08:53:43 +0000 Subject: [PATCH 125/170] feat(CharP): `Int.cast` is injective on `Ico 0 p` (#17063) and generalise `Fin.charP` --- Mathlib/Algebra/CharP/Defs.lean | 12 ++++++++++-- Mathlib/Data/Fin/Basic.lean | 3 ++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Mathlib/Algebra/CharP/Defs.lean b/Mathlib/Algebra/CharP/Defs.lean index b9c236c16d197..d470a6086987e 100644 --- a/Mathlib/Algebra/CharP/Defs.lean +++ b/Mathlib/Algebra/CharP/Defs.lean @@ -18,6 +18,8 @@ import Mathlib.Data.ULift assert_not_exists Finset +open Set + variable (R : Type*) namespace CharP @@ -91,6 +93,13 @@ end AddMonoidWithOne section AddGroupWithOne variable [AddGroupWithOne R] (p : ℕ) [CharP R p] {a b : ℤ} +lemma intCast_injOn_Ico [IsRightCancelAdd R] : InjOn (Int.cast : ℤ → R) (Ico 0 p) := by + rintro a ⟨ha₀, ha⟩ b ⟨hb₀, hb⟩ hab + lift a to ℕ using ha₀ + lift b to ℕ using hb₀ + norm_cast at * + exact natCast_injOn_Iio _ _ ha hb hab + lemma intCast_eq_zero_iff (a : ℤ) : (a : R) = 0 ↔ (p : ℤ) ∣ a := by rcases lt_trichotomy a 0 with (h | rfl | h) · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg] @@ -411,7 +420,6 @@ end CharZero namespace Fin -instance charP (n : ℕ) : CharP (Fin (n + 1)) (n + 1) where - cast_eq_zero_iff' := by simp [Fin.ext_iff, Nat.dvd_iff_mod_eq_zero] +instance charP (n : ℕ) [NeZero n] : CharP (Fin n) n where cast_eq_zero_iff' _ := natCast_eq_zero end Fin diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index ee56f79b0a9e2..7763f1a2b0f45 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -423,7 +423,8 @@ in the same value. -/ -- Porting note: this is syntactically the same as `cast_val_of_lt` -@[simp] lemma natCast_self (n : ℕ) [NeZero n] : (n : Fin n) = 0 := by ext; simp +-- This is a special case of `CharP.cast_eq_zero` that doesn't require typeclass search +@[simp high] lemma natCast_self (n : ℕ) [NeZero n] : (n : Fin n) = 0 := by ext; simp @[deprecated (since := "2024-04-17")] alias nat_cast_self := natCast_self From 9348dae416066dbe9f2f149373df63dc67977bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 24 Sep 2024 09:50:41 +0000 Subject: [PATCH 126/170] chore(SetTheory/Ordinal/Arithmetic): deprecate `ne_iSup_iff_lt_iSup` (#16997) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Yaël [explains](https://github.com/leanprover-community/mathlib4/pull/15820#discussion_r1740447705), this is just an application of `LE.le.lt_iff_ne`. Co-authored-by: Yaël Dillies --- Mathlib/SetTheory/Ordinal/Arithmetic.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 8beea98d87249..c53d3f62b99c5 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -1164,9 +1164,10 @@ set_option linter.deprecated false in theorem lt_sup {ι : Type u} {f : ι → Ordinal.{max u v}} {a} : a < sup.{_, v} f ↔ ∃ i, a < f i := by simpa only [not_forall, not_le] using not_congr (@sup_le_iff.{_, v} _ f a) +@[deprecated (since := "2024-08-27")] theorem ne_iSup_iff_lt_iSup {ι : Type u} {f : ι → Ordinal.{max u v}} : (∀ i, f i ≠ iSup f) ↔ ∀ i, f i < iSup f := - ⟨fun hf _ => lt_of_le_of_ne (Ordinal.le_iSup _ _) (hf _), fun hf _ => ne_of_lt (hf _)⟩ + forall_congr' fun i => (Ordinal.le_iSup f i).lt_iff_ne.symm set_option linter.deprecated false in @[deprecated ne_iSup_iff_lt_iSup (since := "2024-08-27")] From 70a55654deaa80c319f71dcb1ce6c6ea6af2dc4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 24 Sep 2024 11:40:12 +0000 Subject: [PATCH 127/170] refactor: Make `mem_ker` be simp (#17021) Do this for `MonoidHom.mem_ker`, `MonoidHom.mem_mker`, `RingHom.mem_ker`. This matches `LinearMap.mem_ker`. From LeanAPAP --- Mathlib/Algebra/Category/Grp/Kernels.lean | 2 +- Mathlib/Algebra/Group/Subgroup/Basic.lean | 10 +++++----- .../Algebra/Group/Submonoid/Operations.lean | 6 +++--- Mathlib/Algebra/Lie/Submodule.lean | 14 +++++++++----- Mathlib/GroupTheory/Abelianization.lean | 2 +- Mathlib/GroupTheory/PresentedGroup.lean | 4 ++-- Mathlib/GroupTheory/QuotientGroup/Basic.lean | 4 ++-- Mathlib/GroupTheory/Torsion.lean | 2 +- Mathlib/RingTheory/Henselian.lean | 2 +- Mathlib/RingTheory/Ideal/Maps.lean | 19 ++++++++++--------- .../RingTheory/Ideal/QuotientOperations.lean | 4 ++-- Mathlib/RingTheory/IsAdjoinRoot.lean | 2 +- Mathlib/RingTheory/Kaehler/Basic.lean | 8 ++++---- Mathlib/RingTheory/Localization/Algebra.lean | 2 +- Mathlib/RingTheory/Polynomial/Basic.lean | 3 +-- Mathlib/RingTheory/Smooth/Kaehler.lean | 4 ++-- 16 files changed, 46 insertions(+), 42 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/Kernels.lean b/Mathlib/Algebra/Category/Grp/Kernels.lean index 8f367b2c6f460..577c21325b183 100644 --- a/Mathlib/Algebra/Category/Grp/Kernels.lean +++ b/Mathlib/Algebra/Category/Grp/Kernels.lean @@ -26,7 +26,7 @@ def kernelCone : KernelFork f := /-- The kernel of a group homomorphism is a kernel in the categorical sense. -/ def kernelIsLimit : IsLimit <| kernelCone f := Fork.IsLimit.mk _ - (fun s => (by exact Fork.ι s : _ →+ G).codRestrict _ fun c => f.mem_ker.mpr <| + (fun s => (by exact Fork.ι s : _ →+ G).codRestrict _ fun c => mem_ker.mpr <| by exact DFunLike.congr_fun s.condition c) (fun _ => by rfl) (fun _ _ h => ext fun x => Subtype.ext_iff_val.mpr <| by exact DFunLike.congr_fun h x) diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index 9a542a9b6014d..0d13d5ae72a71 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -2134,8 +2134,8 @@ def ker (f : G →* M) : Subgroup G := f x⁻¹ = f x * f x⁻¹ := by rw [hx, one_mul] _ = 1 := by rw [← map_mul, mul_inv_cancel, map_one] } -@[to_additive] -theorem mem_ker (f : G →* M) {x : G} : x ∈ f.ker ↔ f x = 1 := +@[to_additive (attr := simp)] +theorem mem_ker {f : G →* M} {x : G} : x ∈ f.ker ↔ f x = 1 := Iff.rfl @[to_additive] @@ -2155,7 +2155,7 @@ theorem ker_toHomUnits {M} [Monoid M] (f : G →* M) : f.toHomUnits.ker = f.ker theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by constructor <;> intro h · rw [mem_ker, map_mul, h, ← map_mul, inv_mul_cancel, map_one] - · rw [← one_mul x, ← mul_inv_cancel y, mul_assoc, map_mul, f.mem_ker.1 h, mul_one] + · rw [← one_mul x, ← mul_inv_cancel y, mul_assoc, map_mul, mem_ker.1 h, mul_one] @[to_additive] instance decidableMemKer [DecidableEq M] (f : G →* M) : DecidablePred (· ∈ f.ker) := fun x => @@ -2226,7 +2226,7 @@ theorem range_le_ker_iff (f : G →* G') (g : G' →* G'') : f.range ≤ g.ker @[to_additive] instance (priority := 100) normal_ker (f : G →* M) : f.ker.Normal := ⟨fun x hx y => by - rw [mem_ker, map_mul, map_mul, f.mem_ker.1 hx, mul_one, map_mul_eq_one f (mul_inv_cancel y)]⟩ + rw [mem_ker, map_mul, map_mul, mem_ker.1 hx, mul_one, map_mul_eq_one f (mul_inv_cancel y)]⟩ @[to_additive (attr := simp)] lemma ker_fst : ker (fst G G') = .prod ⊥ ⊤ := SetLike.ext fun _ => (iff_of_eq (and_true _)).symm @@ -2599,7 +2599,7 @@ See `MonoidHom.eq_liftOfRightInverse` for the uniqueness lemma. def liftOfRightInverse (hf : Function.RightInverse f_inv f) : { g : G₁ →* G₃ // f.ker ≤ g.ker } ≃ (G₂ →* G₃) where toFun g := f.liftOfRightInverseAux f_inv hf g.1 g.2 - invFun φ := ⟨φ.comp f, fun x hx => (mem_ker _).mpr <| by simp [(mem_ker _).mp hx]⟩ + invFun φ := ⟨φ.comp f, fun x hx ↦ mem_ker.mpr <| by simp [mem_ker.mp hx]⟩ left_inv g := by ext simp only [comp_apply, liftOfRightInverseAux_comp_apply, Subtype.coe_mk] diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index a0ee1b9441d79..1bf4b67f90258 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -865,8 +865,8 @@ that `f x = 1` -/ def mker (f : F) : Submonoid M := (⊥ : Submonoid N).comap f -@[to_additive] -theorem mem_mker (f : F) {x : M} : x ∈ mker f ↔ f x = 1 := +@[to_additive (attr := simp)] +theorem mem_mker {f : F} {x : M} : x ∈ mker f ↔ f x = 1 := Iff.rfl @[to_additive] @@ -875,7 +875,7 @@ theorem coe_mker (f : F) : (mker f : Set M) = (f : M → N) ⁻¹' {1} := @[to_additive] instance decidableMemMker [DecidableEq N] (f : F) : DecidablePred (· ∈ mker f) := fun x => - decidable_of_iff (f x = 1) (mem_mker f) + decidable_of_iff (f x = 1) mem_mker @[to_additive] theorem comap_mker (g : N →* P) (f : M →* N) : g.mker.comap f = mker (comp g f) := diff --git a/Mathlib/Algebra/Lie/Submodule.lean b/Mathlib/Algebra/Lie/Submodule.lean index 3c1f32a790e1d..2fcf4d22646c5 100644 --- a/Mathlib/Algebra/Lie/Submodule.lean +++ b/Mathlib/Algebra/Lie/Submodule.lean @@ -1048,6 +1048,7 @@ theorem ker_le_comap : f.ker ≤ J.comap f := theorem ker_coeSubmodule : LieSubmodule.toSubmodule (ker f) = LinearMap.ker (f : L →ₗ[R] L') := rfl +variable {f} in @[simp] theorem mem_ker {x : L} : x ∈ ker f ↔ f x = 0 := show x ∈ LieSubmodule.toSubmodule (f.ker) ↔ _ by @@ -1155,9 +1156,12 @@ theorem map_sup_ker_eq_map : LieIdeal.map f (I ⊔ f.ker) = LieIdeal.map f I := suffices LieIdeal.map f (I ⊔ f.ker) ≤ LieIdeal.map f I by exact le_antisymm this (LieIdeal.map_mono le_sup_left) apply LieSubmodule.lieSpan_mono - rintro x ⟨y, hy₁, hy₂⟩; rw [← hy₂] - erw [LieSubmodule.mem_sup] at hy₁;obtain ⟨z₁, hz₁, z₂, hz₂, hy⟩ := hy₁; rw [← hy] - rw [f.coe_toLinearMap, f.map_add, f.mem_ker.mp hz₂, add_zero]; exact ⟨z₁, hz₁, rfl⟩ + rintro x ⟨y, hy₁, hy₂⟩ + rw [← hy₂] + erw [LieSubmodule.mem_sup] at hy₁ + obtain ⟨z₁, hz₁, z₂, hz₂, hy⟩ := hy₁ + rw [← hy] + rw [f.coe_toLinearMap, f.map_add, LieHom.mem_ker.mp hz₂, add_zero]; exact ⟨z₁, hz₁, rfl⟩ @[simp] theorem map_sup_ker_eq_map' : @@ -1249,7 +1253,7 @@ theorem ker_eq_bot : f.ker = ⊥ ↔ Function.Injective f := by variable {f} @[simp] -theorem mem_ker (m : M) : m ∈ f.ker ↔ f m = 0 := +theorem mem_ker {m : M} : m ∈ f.ker ↔ f m = 0 := Iff.rfl @[simp] @@ -1257,7 +1261,7 @@ theorem ker_id : (LieModuleHom.id : M →ₗ⁅R,L⁆ M).ker = ⊥ := rfl @[simp] -theorem comp_ker_incl : f.comp f.ker.incl = 0 := by ext ⟨m, hm⟩; exact (mem_ker m).mp hm +theorem comp_ker_incl : f.comp f.ker.incl = 0 := by ext ⟨m, hm⟩; exact mem_ker.mp hm theorem le_ker_iff_map (M' : LieSubmodule R L M) : M' ≤ f.ker ↔ LieSubmodule.map f M' = ⊥ := by rw [ker, eq_bot_iff, LieSubmodule.map_le_iff_le_comap] diff --git a/Mathlib/GroupTheory/Abelianization.lean b/Mathlib/GroupTheory/Abelianization.lean index 51b0cfca00034..5ee8a835a60c4 100644 --- a/Mathlib/GroupTheory/Abelianization.lean +++ b/Mathlib/GroupTheory/Abelianization.lean @@ -125,7 +125,7 @@ theorem commutator_subset_ker : commutator G ≤ f.ker := by /-- If `f : G → A` is a group homomorphism to an abelian group, then `lift f` is the unique map from the abelianization of a `G` to `A` that factors through `f`. -/ def lift : (G →* A) ≃ (Abelianization G →* A) where - toFun f := QuotientGroup.lift _ f fun _ h => f.mem_ker.2 <| commutator_subset_ker _ h + toFun f := QuotientGroup.lift _ f fun _ h => MonoidHom.mem_ker.2 <| commutator_subset_ker _ h invFun F := F.comp of left_inv _ := MonoidHom.ext fun _ => rfl right_inv _ := MonoidHom.ext fun x => QuotientGroup.induction_on x fun _ => rfl diff --git a/Mathlib/GroupTheory/PresentedGroup.lean b/Mathlib/GroupTheory/PresentedGroup.lean index 492c52f336a3f..35916a0da95d5 100644 --- a/Mathlib/GroupTheory/PresentedGroup.lean +++ b/Mathlib/GroupTheory/PresentedGroup.lean @@ -66,11 +66,11 @@ local notation "F" => FreeGroup.lift f theorem closure_rels_subset_ker (h : ∀ r ∈ rels, FreeGroup.lift f r = 1) : Subgroup.normalClosure rels ≤ MonoidHom.ker F := - Subgroup.normalClosure_le_normal fun x w ↦ (MonoidHom.mem_ker _).2 (h x w) + Subgroup.normalClosure_le_normal fun x w ↦ MonoidHom.mem_ker.2 (h x w) theorem to_group_eq_one_of_mem_closure (h : ∀ r ∈ rels, FreeGroup.lift f r = 1) : ∀ x ∈ Subgroup.normalClosure rels, F x = 1 := - fun _ w ↦ (MonoidHom.mem_ker _).1 <| closure_rels_subset_ker h w + fun _ w ↦ MonoidHom.mem_ker.1 <| closure_rels_subset_ker h w /-- The extension of a map `f : α → G` that satisfies the given relations to a group homomorphism from `PresentedGroup rels → G`. -/ diff --git a/Mathlib/GroupTheory/QuotientGroup/Basic.lean b/Mathlib/GroupTheory/QuotientGroup/Basic.lean index a2f47594605f9..7857eb080a61d 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Basic.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Basic.lean @@ -320,7 +320,7 @@ open MonoidHom /-- The induced map from the quotient by the kernel to the codomain. -/ @[to_additive "The induced map from the quotient by the kernel to the codomain."] def kerLift : G ⧸ ker φ →* H := - lift _ φ fun _g => φ.mem_ker.mp + lift _ φ fun _g => mem_ker.mp @[to_additive (attr := simp)] theorem kerLift_mk (g : G) : (kerLift φ) g = φ g := @@ -340,7 +340,7 @@ theorem kerLift_injective : Injective (kerLift φ) := fun a b => /-- The induced map from the quotient by the kernel to the range. -/ @[to_additive "The induced map from the quotient by the kernel to the range."] def rangeKerLift : G ⧸ ker φ →* φ.range := - lift _ φ.rangeRestrict fun g hg => (mem_ker _).mp <| by rwa [ker_rangeRestrict] + lift _ φ.rangeRestrict fun g hg => mem_ker.mp <| by rwa [ker_rangeRestrict] @[to_additive] theorem rangeKerLift_injective : Injective (rangeKerLift φ) := fun a b => diff --git a/Mathlib/GroupTheory/Torsion.lean b/Mathlib/GroupTheory/Torsion.lean index 9e505a267b935..1fe565875fe91 100644 --- a/Mathlib/GroupTheory/Torsion.lean +++ b/Mathlib/GroupTheory/Torsion.lean @@ -91,7 +91,7 @@ theorem IsTorsion.of_surjective {f : G →* H} (hf : Function.Surjective f) (tG theorem IsTorsion.extension_closed {f : G →* H} (hN : N = f.ker) (tH : IsTorsion H) (tN : IsTorsion N) : IsTorsion G := fun g => by obtain ⟨ngn, ngnpos, hngn⟩ := (tH <| f g).exists_pow_eq_one - have hmem := f.mem_ker.mpr ((f.map_pow g ngn).trans hngn) + have hmem := MonoidHom.mem_ker.mpr ((f.map_pow g ngn).trans hngn) lift g ^ ngn to N using hN.symm ▸ hmem with gn h obtain ⟨nn, nnpos, hnn⟩ := (tN gn).exists_pow_eq_one exact isOfFinOrder_iff_pow_eq_one.mpr <| ⟨ngn * nn, mul_pos ngnpos nnpos, by diff --git a/Mathlib/RingTheory/Henselian.lean b/Mathlib/RingTheory/Henselian.lean index ab874dcea2329..c439259451ff0 100644 --- a/Mathlib/RingTheory/Henselian.lean +++ b/Mathlib/RingTheory/Henselian.lean @@ -138,7 +138,7 @@ theorem HenselianLocalRing.TFAE (R : Type u) [CommRing R] [LocalRing R] : | hR, K, _K, φ, hφ, f, hf, a₀, h₁, h₂ => by obtain ⟨a₀, rfl⟩ := hφ a₀ have H := HenselianLocalRing.is_henselian f hf a₀ - simp only [← ker_eq_maximalIdeal φ hφ, eval₂_at_apply, RingHom.mem_ker φ] at H h₁ h₂ + simp only [← ker_eq_maximalIdeal φ hφ, eval₂_at_apply, RingHom.mem_ker] at H h₁ h₂ obtain ⟨a, ha₁, ha₂⟩ := H h₁ (by contrapose! h₂ rwa [← mem_nonunits_iff, ← LocalRing.mem_maximalIdeal, ← LocalRing.ker_eq_maximalIdeal φ hφ, diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index f26dd00db1d4a..1f4675bf75936 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -543,8 +543,9 @@ variable (f : F) (g : G) def ker : Ideal R := Ideal.comap f ⊥ +variable {f} in /-- An element is in the kernel if and only if it maps to zero. -/ -theorem mem_ker {r} : r ∈ ker f ↔ f r = 0 := by rw [ker, Ideal.mem_comap, Submodule.mem_bot] +@[simp] theorem mem_ker {r} : r ∈ ker f ↔ f r = 0 := by rw [ker, Ideal.mem_comap, Submodule.mem_bot] theorem ker_eq : (ker f : Set R) = Set.preimage f {0} := rfl @@ -623,13 +624,13 @@ theorem ker_isMaximal_of_surjective {R K F : Type*} [Ring R] [Field K] (hf : Function.Surjective f) : (ker f).IsMaximal := by refine Ideal.isMaximal_iff.mpr - ⟨fun h1 => one_ne_zero' K <| map_one f ▸ (mem_ker f).mp h1, fun J x hJ hxf hxJ => ?_⟩ + ⟨fun h1 => one_ne_zero' K <| map_one f ▸ mem_ker.mp h1, fun J x hJ hxf hxJ => ?_⟩ obtain ⟨y, hy⟩ := hf (f x)⁻¹ have H : 1 = y * x - (y * x - 1) := (sub_sub_cancel _ _).symm rw [H] refine J.sub_mem (J.mul_mem_left _ hxJ) (hJ ?_) rw [mem_ker] - simp only [hy, map_sub, map_one, map_mul, inv_mul_cancel₀ (mt (mem_ker f).mpr hxf), sub_self] + simp only [hy, map_sub, map_one, map_mul, inv_mul_cancel₀ (mt mem_ker.mpr hxf :), sub_self] end RingHom @@ -645,7 +646,7 @@ theorem map_eq_bot_iff_le_ker {I : Ideal R} (f : F) : I.map f = ⊥ ↔ I ≤ Ri rw [RingHom.ker, eq_bot_iff, map_le_iff_le_comap] theorem ker_le_comap {K : Ideal S} (f : F) : RingHom.ker f ≤ comap f K := fun _ hx => - mem_comap.2 (((RingHom.mem_ker f).1 hx).symm ▸ K.zero_mem) + mem_comap.2 (RingHom.mem_ker.1 hx ▸ K.zero_mem) theorem map_isPrime_of_equiv {F' : Type*} [EquivLike F' R S] [RingEquivClass F' R S] (f : F') {I : Ideal R} [IsPrime I] : IsPrime (map f I) := by @@ -744,15 +745,15 @@ def liftOfRightInverseAux (hf : Function.RightInverse f_inv f) (g : A →+* C) { AddMonoidHom.liftOfRightInverse f.toAddMonoidHom f_inv hf ⟨g.toAddMonoidHom, hg⟩ with toFun := fun b => g (f_inv b) map_one' := by - rw [← map_one g, ← sub_eq_zero, ← map_sub g, ← mem_ker g] + rw [← map_one g, ← sub_eq_zero, ← map_sub g, ← mem_ker] apply hg - rw [mem_ker f, map_sub f, sub_eq_zero, map_one f] + rw [mem_ker, map_sub f, sub_eq_zero, map_one f] exact hf 1 map_mul' := by intro x y - rw [← map_mul g, ← sub_eq_zero, ← map_sub g, ← mem_ker g] + rw [← map_mul g, ← sub_eq_zero, ← map_sub g, ← mem_ker] apply hg - rw [mem_ker f, map_sub f, sub_eq_zero, map_mul f] + rw [mem_ker, map_sub f, sub_eq_zero, map_mul f] simp only [hf _] } @[simp] @@ -782,7 +783,7 @@ See `RingHom.eq_liftOfRightInverse` for the uniqueness lemma. def liftOfRightInverse (hf : Function.RightInverse f_inv f) : { g : A →+* C // RingHom.ker f ≤ RingHom.ker g } ≃ (B →+* C) where toFun g := f.liftOfRightInverseAux f_inv hf g.1 g.2 - invFun φ := ⟨φ.comp f, fun x hx => (mem_ker _).mpr <| by simp [(mem_ker _).mp hx]⟩ + invFun φ := ⟨φ.comp f, fun x hx => mem_ker.mpr <| by simp [mem_ker.mp hx]⟩ left_inv g := by ext simp only [comp_apply, liftOfRightInverseAux_comp_apply, Subtype.coe_mk] diff --git a/Mathlib/RingTheory/Ideal/QuotientOperations.lean b/Mathlib/RingTheory/Ideal/QuotientOperations.lean index 7abf1424f8ab5..5fb624f6f2143 100644 --- a/Mathlib/RingTheory/Ideal/QuotientOperations.lean +++ b/Mathlib/RingTheory/Ideal/QuotientOperations.lean @@ -36,7 +36,7 @@ This is an isomorphism if `f` has a right inverse (`quotientKerEquivOfRightInver is surjective (`quotientKerEquivOfSurjective`). -/ def kerLift : R ⧸ ker f →+* S := - Ideal.Quotient.lift _ f fun _ => f.mem_ker.mp + Ideal.Quotient.lift _ f fun _ => mem_ker.mp @[simp] theorem kerLift_mk (r : R) : kerLift f (Ideal.Quotient.mk (ker f) r) = f r := @@ -49,7 +49,7 @@ theorem lift_injective_of_ker_le_ideal (I : Ideal R) {f : R →+* S} (H : ∀ a obtain ⟨v, rfl⟩ := Ideal.Quotient.mk_surjective u rw [Ideal.Quotient.lift_mk] at hu rw [Ideal.Quotient.eq_zero_iff_mem] - exact hI ((RingHom.mem_ker f).mpr hu) + exact hI (RingHom.mem_ker.mpr hu) /-- The induced map from the quotient by the kernel is injective. -/ theorem kerLift_injective : Function.Injective (kerLift f) := diff --git a/Mathlib/RingTheory/IsAdjoinRoot.lean b/Mathlib/RingTheory/IsAdjoinRoot.lean index 03e036aa35719..1b153b9e33498 100644 --- a/Mathlib/RingTheory/IsAdjoinRoot.lean +++ b/Mathlib/RingTheory/IsAdjoinRoot.lean @@ -121,10 +121,10 @@ theorem subsingleton (h : IsAdjoinRoot S f) [Subsingleton R] : Subsingleton S := theorem algebraMap_apply (h : IsAdjoinRoot S f) (x : R) : algebraMap R S x = h.map (Polynomial.C x) := by rw [h.algebraMap_eq, RingHom.comp_apply] -@[simp] theorem mem_ker_map (h : IsAdjoinRoot S f) {p} : p ∈ RingHom.ker h.map ↔ f ∣ p := by rw [h.ker_map, Ideal.mem_span_singleton] +@[simp] theorem map_eq_zero_iff (h : IsAdjoinRoot S f) {p} : h.map p = 0 ↔ f ∣ p := by rw [← h.mem_ker_map, RingHom.mem_ker] diff --git a/Mathlib/RingTheory/Kaehler/Basic.lean b/Mathlib/RingTheory/Kaehler/Basic.lean index 4c0d923b7ddfc..09bc7c6dc0c45 100644 --- a/Mathlib/RingTheory/Kaehler/Basic.lean +++ b/Mathlib/RingTheory/Kaehler/Basic.lean @@ -808,7 +808,7 @@ def KaehlerDifferential.kerToTensor : map_add' x y := by simp only [Submodule.coe_add, map_add, TensorProduct.tmul_add] map_smul' r x := by simp only [SetLike.val_smul, smul_eq_mul, Derivation.leibniz, TensorProduct.tmul_add, TensorProduct.tmul_smul, TensorProduct.smul_tmul', ← - algebraMap_eq_smul_one, (RingHom.mem_ker _).mp x.prop, TensorProduct.zero_tmul, add_zero, + algebraMap_eq_smul_one, RingHom.mem_ker.mp x.prop, TensorProduct.zero_tmul, add_zero, RingHom.id_apply] /-- The map `I/I² → B ⊗[A] B ⊗[A] Ω[A⁄R]` where `I = ker(A → B)`. -/ @@ -820,7 +820,7 @@ def KaehlerDifferential.kerCotangentToTensor : rintro x hx y - simp only [Submodule.mem_comap, LinearMap.lsmul_apply, LinearMap.mem_ker, map_smul, kerToTensor_apply, TensorProduct.smul_tmul', ← algebraMap_eq_smul_one, - (RingHom.mem_ker _).mp hx, TensorProduct.zero_tmul])) + RingHom.mem_ker.mp hx, TensorProduct.zero_tmul])) @[simp] lemma KaehlerDifferential.kerCotangentToTensor_toCotangent (x) : @@ -837,7 +837,7 @@ theorem KaehlerDifferential.range_kerCotangentToTensor constructor · rintro ⟨x, rfl⟩ obtain ⟨x, rfl⟩ := Ideal.toCotangent_surjective _ x - simp [kerCotangentToTensor_toCotangent, (RingHom.mem_ker _).mp x.2] + simp [kerCotangentToTensor_toCotangent, RingHom.mem_ker.mp x.2] · intro hx obtain ⟨x, rfl⟩ := LinearMap.rTensor_surjective (Ω[A⁄R]) (g := Algebra.linearMap A B) h x obtain ⟨x, rfl⟩ := (TensorProduct.lid _ _).symm.surjective x @@ -870,7 +870,7 @@ theorem KaehlerDifferential.range_kerCotangentToTensor simp only [smul_sub, TensorProduct.tmul_sub, Finset.sum_sub_distrib, ← TensorProduct.tmul_sum, ← Finset.sum_smul, Finset.sum_attach, sub_eq_self, Finset.sum_attach (f := fun i ↦ x i • KaehlerDifferential.D R A i)] - rw [← TensorProduct.smul_tmul, ← Algebra.algebraMap_eq_smul_one, (RingHom.mem_ker _).mp this, + rw [← TensorProduct.smul_tmul, ← Algebra.algebraMap_eq_smul_one, RingHom.mem_ker.mp this, TensorProduct.zero_tmul] theorem KaehlerDifferential.exact_kerCotangentToTensor_mapBaseChange diff --git a/Mathlib/RingTheory/Localization/Algebra.lean b/Mathlib/RingTheory/Localization/Algebra.lean index b92decb0ad796..794c17c9aea4a 100644 --- a/Mathlib/RingTheory/Localization/Algebra.lean +++ b/Mathlib/RingTheory/Localization/Algebra.lean @@ -56,7 +56,7 @@ variable (S) in /-- The canonical linear map from the kernel of `g` to the kernel of its localization. -/ def RingHom.toKerIsLocalization (hy : M ≤ Submonoid.comap g T) : RingHom.ker g →ₗ[R] RingHom.ker (IsLocalization.map Q g hy : S →+* Q) where - toFun x := ⟨algebraMap R S x, by simp [RingHom.mem_ker, (RingHom.mem_ker g).mp x.property]⟩ + toFun x := ⟨algebraMap R S x, by simp [RingHom.mem_ker, RingHom.mem_ker.mp x.property]⟩ map_add' x y := by simp only [Submodule.coe_add, map_add, AddMemClass.mk_add_mk] map_smul' a x := by diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index fe44dfcd045fe..ab6d03ba20af2 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -605,8 +605,7 @@ theorem _root_.Polynomial.ker_mapRingHom (f : R →+* S) : ext simp only [LinearMap.mem_ker, RingHom.toSemilinearMap_apply, coe_mapRingHom] rw [mem_map_C_iff, Polynomial.ext_iff] - simp_rw [RingHom.mem_ker f] - simp + simp [RingHom.mem_ker] variable (I : Ideal R[X]) diff --git a/Mathlib/RingTheory/Smooth/Kaehler.lean b/Mathlib/RingTheory/Smooth/Kaehler.lean index 0e20b7e631d12..e11be1b55e317 100644 --- a/Mathlib/RingTheory/Smooth/Kaehler.lean +++ b/Mathlib/RingTheory/Smooth/Kaehler.lean @@ -112,7 +112,7 @@ lemma retractionOfSectionOfKerSqZero_tmul_D (s : S) (t : P) : lemma retractionOfSectionOfKerSqZero_comp_kerToTensor : (retractionOfSectionOfKerSqZero g hf' hg).comp (kerToTensor R P S) = LinearMap.id := by - ext x; simp [(RingHom.mem_ker _).mp x.2] + ext x; simp [RingHom.mem_ker.mp x.2] end ofSection @@ -172,7 +172,7 @@ lemma toAlgHom_comp_sectionOfRetractionKerToTensorAux : (sectionOfRetractionKerToTensorAux l hl σ hσ hf') = AlgHom.id _ _ := by ext x obtain ⟨x, rfl⟩ := hf x - simp [sectionOfRetractionKerToTensorAux_algebraMap, (RingHom.mem_ker _).mp] + simp [sectionOfRetractionKerToTensorAux_algebraMap, RingHom.mem_ker.mp] /-- Given a surjective algebra homomorphism `f : P →ₐ[R] S` with square-zero kernel `I`. From c01c9ce08718bb7677d43dee3afc516933ced76c Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Tue, 24 Sep 2024 12:27:37 +0000 Subject: [PATCH 128/170] feat(CategoryTheory): The whiskering functor preserves identity and composition of functors (#16971) --- Mathlib/CategoryTheory/Whiskering.lean | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Mathlib/CategoryTheory/Whiskering.lean b/Mathlib/CategoryTheory/Whiskering.lean index 7971db9d070c7..50cc4f617eec0 100644 --- a/Mathlib/CategoryTheory/Whiskering.lean +++ b/Mathlib/CategoryTheory/Whiskering.lean @@ -113,6 +113,46 @@ def Functor.FullyFaithful.whiskeringRight {F : D ⥤ E} (hF : F.FullyFaithful) simp only [map_comp, map_preimage] apply f.naturality } +theorem whiskeringLeft_obj_id : (whiskeringLeft C C E).obj (𝟭 _) = 𝟭 _ := + rfl + +/-- The isomorphism between left-whiskering on the identity functor and the identity of the functor +between the resulting functor categories. -/ +def whiskeringLeftObjIdIso : (whiskeringLeft C C E).obj (𝟭 _) ≅ 𝟭 _ := + Iso.refl _ + +theorem whiskeringLeft_obj_comp {D' : Type u₄} [Category.{v₄} D'] (F : C ⥤ D) (G : D ⥤ D') : + (whiskeringLeft C D' E).obj (F ⋙ G) = + (whiskeringLeft D D' E).obj G ⋙ (whiskeringLeft C D E).obj F := + rfl + +/-- The isomorphism between left-whiskering on the composition of functors and the composition +of two left-whiskering applications. -/ +def whiskeringLeftObjCompIso {D' : Type u₄} [Category.{v₄} D'] (F : C ⥤ D) (G : D ⥤ D') : + (whiskeringLeft C D' E).obj (F ⋙ G) ≅ + (whiskeringLeft D D' E).obj G ⋙ (whiskeringLeft C D E).obj F := + Iso.refl _ + +theorem whiskeringRight_obj_id : (whiskeringRight E C C).obj (𝟭 _) = 𝟭 _ := + rfl + +/-- The isomorphism between right-whiskering on the identity functor and the identity of the functor +between the resulting functor categories. -/ +def wiskeringRightObjIdIso : (whiskeringRight E C C).obj (𝟭 _) ≅ 𝟭 _ := + Iso.refl _ + +theorem whiskeringRight_obj_comp {D' : Type u₄} [Category.{v₄} D'] (F : C ⥤ D) (G : D ⥤ D') : + (whiskeringRight E C D).obj F ⋙ (whiskeringRight E D D').obj G = + (whiskeringRight E C D').obj (F ⋙ G) := + rfl + +/-- The isomorphism between right-whiskering on the composition of functors and the composition +of two right-whiskering applications. -/ +def whiskeringRightObjCompIso {D' : Type u₄} [Category.{v₄} D'] (F : C ⥤ D) (G : D ⥤ D') : + (whiskeringRight E C D).obj F ⋙ (whiskeringRight E D D').obj G ≅ + (whiskeringRight E C D').obj (F ⋙ G) := + Iso.refl _ + instance full_whiskeringRight_obj {F : D ⥤ E} [F.Faithful] [F.Full] : ((whiskeringRight C D E).obj F).Full := ((Functor.FullyFaithful.ofFullyFaithful F).whiskeringRight C).full From a6954b3788a62acda6a0e99ab1548255a1d1e8ae Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 24 Sep 2024 12:27:38 +0000 Subject: [PATCH 129/170] chore(Order/Group): golf (#17079) ... using lemmas like `monotone_int_of_le_succ` --- Mathlib/Algebra/Order/Group/Basic.lean | 37 +++++++++++--------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/Mathlib/Algebra/Order/Group/Basic.lean b/Mathlib/Algebra/Order/Group/Basic.lean index 9c07d497a0c75..bc99b34b1b895 100644 --- a/Mathlib/Algebra/Order/Group/Basic.lean +++ b/Mathlib/Algebra/Order/Group/Basic.lean @@ -20,39 +20,32 @@ variable {α M R : Type*} section OrderedCommGroup variable [OrderedCommGroup α] {m n : ℤ} {a b : α} -@[to_additive zsmul_pos] lemma one_lt_zpow' (ha : 1 < a) (hn : 0 < n) : 1 < a ^ n := by - obtain ⟨n, rfl⟩ := Int.eq_ofNat_of_zero_le hn.le - rw [zpow_natCast] - refine one_lt_pow' ha ?_ - rintro rfl - simp at hn - @[to_additive zsmul_left_strictMono] -lemma zpow_right_strictMono (ha : 1 < a) : StrictMono fun n : ℤ ↦ a ^ n := fun m n h ↦ - calc - a ^ m = a ^ m * 1 := (mul_one _).symm - _ < a ^ m * a ^ (n - m) := mul_lt_mul_left' (one_lt_zpow' ha <| Int.sub_pos_of_lt h) _ - _ = a ^ n := by simp [← zpow_add, m.add_comm] +lemma zpow_right_strictMono (ha : 1 < a) : StrictMono fun n : ℤ ↦ a ^ n := by + refine strictMono_int_of_lt_succ fun n ↦ ?_ + rw [zpow_add_one] + exact lt_mul_of_one_lt_right' (a ^ n) ha @[deprecated (since := "2024-09-19")] alias zsmul_strictMono_left := zsmul_left_strictMono +@[to_additive zsmul_pos] lemma one_lt_zpow' (ha : 1 < a) (hn : 0 < n) : 1 < a ^ n := by + simpa using zpow_right_strictMono ha hn + @[to_additive zsmul_left_strictAnti] -lemma zpow_right_strictAnti (ha : a < 1) : StrictAnti fun n : ℤ ↦ a ^ n := fun m n h ↦ calc - a ^ n < a ^ n * a⁻¹ ^ (n - m) := - lt_mul_of_one_lt_right' _ <| one_lt_zpow' (one_lt_inv'.2 ha) <| Int.sub_pos.2 h - _ = a ^ m := by - rw [inv_zpow', Int.neg_sub, ← zpow_add, Int.add_comm, Int.sub_add_cancel] +lemma zpow_right_strictAnti (ha : a < 1) : StrictAnti fun n : ℤ ↦ a ^ n := by + refine strictAnti_int_of_succ_lt fun n ↦ ?_ + rw [zpow_add_one] + exact mul_lt_of_lt_one_right' (a ^ n) ha @[to_additive zsmul_left_inj] lemma zpow_right_inj (ha : 1 < a) {m n : ℤ} : a ^ m = a ^ n ↔ m = n := (zpow_right_strictMono ha).injective.eq_iff @[to_additive zsmul_mono_left] -lemma zpow_mono_right (ha : 1 ≤ a) : Monotone fun n : ℤ ↦ a ^ n := fun m n h ↦ - calc - a ^ m = a ^ m * 1 := (mul_one _).symm - _ ≤ a ^ m * a ^ (n - m) := mul_le_mul_left' (one_le_zpow ha <| Int.sub_nonneg_of_le h) _ - _ = a ^ n := by simp [← zpow_add, m.add_comm] +lemma zpow_mono_right (ha : 1 ≤ a) : Monotone fun n : ℤ ↦ a ^ n := by + refine monotone_int_of_le_succ fun n ↦ ?_ + rw [zpow_add_one] + exact le_mul_of_one_le_right' ha @[to_additive (attr := gcongr)] lemma zpow_le_zpow (ha : 1 ≤ a) (h : m ≤ n) : a ^ m ≤ a ^ n := zpow_mono_right ha h From 60ff730156569b4560f2648efad59dbaf98b96a9 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Tue, 24 Sep 2024 13:23:52 +0000 Subject: [PATCH 130/170] chore(.github): add cross references between autogenerated files and master file (#17090) --- .github/build.in.yml | 6 +++++- .github/workflows/bors.yml | 3 ++- .github/workflows/build.yml | 3 ++- .github/workflows/build_fork.yml | 3 ++- .github/workflows/mk_build_yml.sh | 5 +++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/build.in.yml b/.github/build.in.yml index 0681d86ddadf3..7a5fc57e42d7b 100644 --- a/.github/build.in.yml +++ b/.github/build.in.yml @@ -1,4 +1,8 @@ -# This is the master file for autogenerating `.github/workflows/{bors, build_fork, build }.yml`. +### NB: This is the master file for autogenerating +### NB: `.github/workflows/{bors, build_fork, build}.yml`. +### NB: If you need to edit any of those files, you should edit this file instead, +### NB: and regenerate those files by manually running +### NB: .github/workflows/mk_build_yml.sh jobs: # Cancels previous runs of jobs in this file diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index 02e70351023a5..2d3b247327d23 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -1,7 +1,8 @@ # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run +# .github/workflows/mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly # The jobs in this file run on self-hosted workers and will not be run from external forks diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd482c1de4509..245362dfe5d7c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,8 @@ # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run +# .github/workflows/mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly # The jobs in this file run on self-hosted workers and will not be run from external forks diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index f08ba63897a50..5c3fa8a2099b1 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -1,7 +1,8 @@ # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run +# .github/workflows/mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly # The jobs in this file run on GitHub-hosted workers and will only be run from external forks diff --git a/.github/workflows/mk_build_yml.sh b/.github/workflows/mk_build_yml.sh index 316ccf3bf5bb2..435e7b4e4c6dc 100755 --- a/.github/workflows/mk_build_yml.sh +++ b/.github/workflows/mk_build_yml.sh @@ -13,7 +13,8 @@ header() { # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run +# .github/workflows/mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly EOF @@ -82,7 +83,7 @@ include() { s/MAIN_OR_FORK/$3/g; s/JOB_NAME/$4/g; s/STYLE_LINT_RUNNER/$5/g; - /^#.*autogenerating/d + /^### NB/d " ../build.in.yml } From b479ce63ba159bc287f99242ed9fb313ea7668da Mon Sep 17 00:00:00 2001 From: Yongle Hu Date: Tue, 24 Sep 2024 15:04:44 +0000 Subject: [PATCH 131/170] chore(Mathlib/RingTheory/LocalProperties): split LocalProperties.lean (#16879) Split the section on local properties in general and the properties that satisfy local properties in `LocalProperties.lean` into separate files. See the discussions [here](https://github.com/leanprover-community/mathlib4/pull/16558#discussion_r1761381528). Co-authored-by: Hu Yongle <2065545849@qq.com> Co-authored-by: Yongle Hu <2065545849@qq.com> --- Mathlib.lean | 4 +- .../Morphisms/ClosedImmersion.lean | 4 +- .../Morphisms/Preimmersion.lean | 4 +- .../Morphisms/RingHomProperties.lean | 2 +- Mathlib/AlgebraicGeometry/Properties.lean | 5 +- Mathlib/RingTheory/Ideal/Norm.lean | 2 +- .../IntegralClosure/IntegralRestrict.lean | 8 +- .../IntegralClosure/IntegrallyClosed.lean | 40 +- Mathlib/RingTheory/LocalProperties.lean | 709 ------------------ Mathlib/RingTheory/LocalProperties/Basic.lean | 332 ++++++++ .../LocalProperties/IntegrallyClosed.lean | 68 ++ .../RingTheory/LocalProperties/Reduced.lean | 53 ++ .../RingTheory/Localization/Finiteness.lean | 2 +- Mathlib/RingTheory/RingHom/Finite.lean | 195 ++++- Mathlib/RingTheory/RingHom/FiniteType.lean | 136 +++- Mathlib/RingTheory/RingHom/Surjective.lean | 69 +- 16 files changed, 842 insertions(+), 791 deletions(-) delete mode 100644 Mathlib/RingTheory/LocalProperties.lean create mode 100644 Mathlib/RingTheory/LocalProperties/Basic.lean create mode 100644 Mathlib/RingTheory/LocalProperties/IntegrallyClosed.lean create mode 100644 Mathlib/RingTheory/LocalProperties/Reduced.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4de0c7bf38993..cc970198038fa 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3920,7 +3920,9 @@ import Mathlib.RingTheory.Kaehler.CotangentComplex import Mathlib.RingTheory.Kaehler.Polynomial import Mathlib.RingTheory.LaurentSeries import Mathlib.RingTheory.LittleWedderburn -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.LocalProperties.Basic +import Mathlib.RingTheory.LocalProperties.IntegrallyClosed +import Mathlib.RingTheory.LocalProperties.Reduced import Mathlib.RingTheory.LocalRing.Basic import Mathlib.RingTheory.LocalRing.Defs import Mathlib.RingTheory.LocalRing.MaximalIdeal.Basic diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index 4affb2c6194ba..4eedb17248903 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -95,11 +95,11 @@ theorem spec_of_surjective {R S : CommRingCat} (f : R ⟶ S) (h : Function.Surje surj_on_stalks x := by haveI : (RingHom.toMorphismProperty (fun f ↦ Function.Surjective f)).RespectsIso := by rw [← RingHom.toMorphismProperty_respectsIso_iff] - exact surjective_respectsIso + exact RingHom.surjective_respectsIso apply (MorphismProperty.arrow_mk_iso_iff (RingHom.toMorphismProperty (fun f ↦ Function.Surjective f)) (Scheme.arrowStalkMapSpecIso f x)).mpr - exact surjective_localRingHom_of_surjective f h x.asIdeal + exact RingHom.surjective_localRingHom_of_surjective f h x.asIdeal /-- For any ideal `I` in a commutative ring `R`, the quotient map `specObj R ⟶ specObj (R ⧸ I)` is a closed immersion. -/ diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean index 25d3e57f11b98..b9472fc3ea550 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.Morphisms.UnderlyingMap -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.RingHom.Surjective /-! @@ -52,7 +52,7 @@ lemma isPreimmersion_eq_inf : /-- Being surjective on stalks is local at the target. -/ instance isSurjectiveOnStalks_isLocalAtTarget : IsLocalAtTarget (stalkwise (Function.Surjective ·)) := - stalkwiseIsLocalAtTarget_of_respectsIso surjective_respectsIso + stalkwiseIsLocalAtTarget_of_respectsIso RingHom.surjective_respectsIso namespace IsPreimmersion diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index fe7b94f0420b3..1a867be2b4d2a 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.Morphisms.Basic -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.LocalProperties.Basic /-! diff --git a/Mathlib/AlgebraicGeometry/Properties.lean b/Mathlib/AlgebraicGeometry/Properties.lean index d4cb9d574a2c2..70e632782f02a 100644 --- a/Mathlib/AlgebraicGeometry/Properties.lean +++ b/Mathlib/AlgebraicGeometry/Properties.lean @@ -4,10 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.AffineScheme -import Mathlib.RingTheory.Nilpotent.Lemmas -import Mathlib.Topology.Sheaves.SheafCondition.Sites -import Mathlib.Algebra.Category.Ring.Constructions -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.LocalProperties.Reduced /-! # Basic properties of schemes diff --git a/Mathlib/RingTheory/Ideal/Norm.lean b/Mathlib/RingTheory/Ideal/Norm.lean index b30d0820ffb94..6e1a0aa1de64f 100644 --- a/Mathlib/RingTheory/Ideal/Norm.lean +++ b/Mathlib/RingTheory/Ideal/Norm.lean @@ -12,7 +12,7 @@ import Mathlib.LinearAlgebra.FreeModule.Determinant import Mathlib.LinearAlgebra.FreeModule.IdealQuotient import Mathlib.RingTheory.DedekindDomain.PID import Mathlib.RingTheory.Ideal.Basis -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.LocalProperties.Basic import Mathlib.RingTheory.Localization.NormTrace /-! diff --git a/Mathlib/RingTheory/IntegralClosure/IntegralRestrict.lean b/Mathlib/RingTheory/IntegralClosure/IntegralRestrict.lean index f0f556d8c02f6..5253fd9dff111 100644 --- a/Mathlib/RingTheory/IntegralClosure/IntegralRestrict.lean +++ b/Mathlib/RingTheory/IntegralClosure/IntegralRestrict.lean @@ -3,11 +3,11 @@ Copyright (c) 2023 Andrew Yang, Patrick Lutz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.RingTheory.IntegralClosure.IntegrallyClosed -import Mathlib.RingTheory.LocalProperties -import Mathlib.RingTheory.Localization.NormTrace -import Mathlib.RingTheory.Localization.LocalizationLocalization import Mathlib.RingTheory.DedekindDomain.IntegralClosure +import Mathlib.RingTheory.RingHom.Finite +import Mathlib.RingTheory.Localization.LocalizationLocalization +import Mathlib.RingTheory.Localization.NormTrace + /-! # Restriction of various maps between fields to integrally closed subrings. diff --git a/Mathlib/RingTheory/IntegralClosure/IntegrallyClosed.lean b/Mathlib/RingTheory/IntegralClosure/IntegrallyClosed.lean index bca52f16d811e..c987ccc2c77c5 100644 --- a/Mathlib/RingTheory/IntegralClosure/IntegrallyClosed.lean +++ b/Mathlib/RingTheory/IntegralClosure/IntegrallyClosed.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ import Mathlib.RingTheory.Localization.Integral -import Mathlib.RingTheory.Localization.LocalizationLocalization /-! # Integrally closed rings @@ -278,44 +277,7 @@ end integralClosure /-- Any field is integral closed. -/ /- Although `infer_instance` can find this if you import Mathlib, in this file they have not been - proven yet. However, the next theorem is a fundamental property of `IsIntegrallyClosed`, + proven yet. However, it is used to prove a fundamental property of `IsIntegrallyClosed`, and it is not desirable to involve more content from other files. -/ instance Field.instIsIntegrallyClosed (K : Type*) [Field K] : IsIntegrallyClosed K := (isIntegrallyClosed_iff K).mpr fun {x} _ ↦ ⟨x, rfl⟩ - -open Localization Ideal IsLocalization in -/-- An integral domain `R` is integral closed if `Rₘ` is integral closed -for any maximal ideal `m` of `R`. -/ -theorem IsIntegrallyClosed.of_localization_maximal {R : Type*} [CommRing R] [IsDomain R] - (h : ∀ p : Ideal R, p ≠ ⊥ → [p.IsMaximal] → IsIntegrallyClosed (Localization.AtPrime p)) : - IsIntegrallyClosed R := by - by_cases hf : IsField R - · exact hf.toField.instIsIntegrallyClosed - apply (isIntegrallyClosed_iff (FractionRing R)).mpr - rintro ⟨x⟩ hx - let I : Ideal R := span {x.2.1} / span {x.1} - have h1 : 1 ∈ I := by - apply I.eq_top_iff_one.mp - by_contra hn - rcases I.exists_le_maximal hn with ⟨p, hpm, hpi⟩ - have hic := h p (Ring.ne_bot_of_isMaximal_of_not_isField hpm hf) - have hxp : IsIntegral (Localization.AtPrime p) (mk x.1 x.2) := hx.tower_top - /- `x.1 / x.2.1 ∈ Rₚ` since it is integral over `Rₚ` and `Rₚ` is integrally closed. - More precisely, `x.1 / x.2.1 = y.1 / y.2.1` where `y.1, y.2.1 ∈ R` and `y.2.1 ∉ p`. -/ - rcases (isIntegrallyClosed_iff (FractionRing R)).mp hic hxp with ⟨⟨y⟩, hy⟩ - /- `y.2.1 ∈ I` since for all `a ∈ Ideal.span {x.1}`, say `a = b * x.1`, - we have `y.2 * a = b * x.1 * y.2 = b * y.1 * x.2.1 ∈ Ideal.span {x.2.1}`. -/ - have hyi : y.2.1 ∈ I := by - intro a ha - rcases mem_span_singleton'.mp ha with ⟨b, hb⟩ - apply mem_span_singleton'.mpr ⟨b * y.1, _⟩ - rw [← hb, ← mul_assoc, mul_comm y.2.1 b, mul_assoc, mul_assoc] - exact congrArg (HMul.hMul b) <| (mul_comm y.1 x.2.1).trans <| - NoZeroSMulDivisors.algebraMap_injective R (Localization R⁰) <| mk'_eq_iff_eq.mp <| - (mk'_eq_algebraMap_mk'_of_submonoid_le _ _ p.primeCompl_le_nonZeroDivisors y.1 y.2).trans - <| show algebraMap (Localization.AtPrime p) _ (mk' _ y.1 y.2) = mk' _ x.1 x.2 - by simpa only [← mk_eq_mk', ← hy] using by rfl - -- `y.2.1 ∈ I` implies `y.2.1 ∈ p` since `I ⊆ p`, which contradicts to the choice of `y`. - exact y.2.2 (hpi hyi) - rcases mem_span_singleton'.mp (h1 x.1 (mem_span_singleton_self x.1)) with ⟨y, hy⟩ - exact ⟨y, (eq_mk'_of_mul_eq (hy.trans (one_mul x.1))).trans (mk_eq_mk'_apply x.1 x.2).symm⟩ diff --git a/Mathlib/RingTheory/LocalProperties.lean b/Mathlib/RingTheory/LocalProperties.lean deleted file mode 100644 index 8add67ec8ef96..0000000000000 --- a/Mathlib/RingTheory/LocalProperties.lean +++ /dev/null @@ -1,709 +0,0 @@ -/- -Copyright (c) 2021 Andrew Yang. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Andrew Yang --/ -import Mathlib.RingTheory.Localization.Submodule -import Mathlib.RingTheory.RingHomProperties -import Mathlib.RingTheory.IntegralClosure.IntegrallyClosed - -/-! -# Local properties of commutative rings - -In this file, we provide the proofs of various local properties. - -## Naming Conventions - -* `localization_P` : `P` holds for `S⁻¹R` if `P` holds for `R`. -* `P_of_localization_maximal` : `P` holds for `R` if `P` holds for `Rₘ` for all maximal `m`. -* `P_of_localization_prime` : `P` holds for `R` if `P` holds for `Rₘ` for all prime `m`. -* `P_ofLocalizationSpan` : `P` holds for `R` if given a spanning set `{fᵢ}`, `P` holds for all - `R_{fᵢ}`. - -## Main results - -The following properties are covered: - -* The triviality of an ideal or an element: - `ideal_eq_bot_of_localization`, `eq_zero_of_localization` -* `IsReduced` : `localization_isReduced`, `isReduced_of_localization_maximal`. -* `RingHom.finite`: `localization_finite`, `finite_ofLocalizationSpan` -* `RingHom.finiteType`: `localization_finiteType`, `finiteType_ofLocalizationSpan` - --/ - -open scoped Pointwise Classical - -universe u - -variable {R S : Type u} [CommRing R] [CommRing S] (M : Submonoid R) -variable (N : Submonoid S) (R' S' : Type u) [CommRing R'] [CommRing S'] (f : R →+* S) -variable [Algebra R R'] [Algebra S S'] - -section Properties - -section CommRing - -variable (P : ∀ (R : Type u) [CommRing R], Prop) - -/-- A property `P` of comm rings is said to be preserved by localization - if `P` holds for `M⁻¹R` whenever `P` holds for `R`. -/ -def LocalizationPreserves : Prop := - ∀ {R : Type u} [hR : CommRing R] (M : Submonoid R) (S : Type u) [hS : CommRing S] [Algebra R S] - [IsLocalization M S], @P R hR → @P S hS - -/-- A property `P` of comm rings satisfies `OfLocalizationMaximal` - if `P` holds for `R` whenever `P` holds for `Rₘ` for all maximal ideal `m`. -/ -def OfLocalizationMaximal : Prop := - ∀ (R : Type u) [CommRing R], - (∀ (J : Ideal R) (_ : J.IsMaximal), P (Localization.AtPrime J)) → P R - -end CommRing - -section RingHom - -variable (P : ∀ {R S : Type u} [CommRing R] [CommRing S] (_ : R →+* S), Prop) - -/-- A property `P` of ring homs is said to contain identities if `P` holds -for the identity homomorphism of every ring. -/ -def RingHom.ContainsIdentities := ∀ (R : Type u) [CommRing R], P (RingHom.id R) - -/-- A property `P` of ring homs is said to be preserved by localization - if `P` holds for `M⁻¹R →+* M⁻¹S` whenever `P` holds for `R →+* S`. -/ -def RingHom.LocalizationPreserves := - ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (M : Submonoid R) (R' S' : Type u) - [CommRing R'] [CommRing S'] [Algebra R R'] [Algebra S S'] [IsLocalization M R'] - [IsLocalization (M.map f) S'], - P f → P (IsLocalization.map S' f (Submonoid.le_comap_map M) : R' →+* S') - -/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpan` -if `P` holds for `R →+* S` whenever there exists a finite set `{ r }` that spans `R` such that -`P` holds for `Rᵣ →+* Sᵣ`. - -Note that this is equivalent to `RingHom.OfLocalizationSpan` via -`RingHom.ofLocalizationSpan_iff_finite`, but this is easier to prove. -/ -def RingHom.OfLocalizationFiniteSpan := - ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Finset R) - (_ : Ideal.span (s : Set R) = ⊤) (_ : ∀ r : s, P (Localization.awayMap f r)), P f - -/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpan` -if `P` holds for `R →+* S` whenever there exists a set `{ r }` that spans `R` such that -`P` holds for `Rᵣ →+* Sᵣ`. - -Note that this is equivalent to `RingHom.OfLocalizationFiniteSpan` via -`RingHom.ofLocalizationSpan_iff_finite`, but this has less restrictions when applying. -/ -def RingHom.OfLocalizationSpan := - ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Set R) (_ : Ideal.span s = ⊤) - (_ : ∀ r : s, P (Localization.awayMap f r)), P f - -/-- A property `P` of ring homs satisfies `RingHom.HoldsForLocalizationAway` - if `P` holds for each localization map `R →+* Rᵣ`. -/ -def RingHom.HoldsForLocalizationAway : Prop := - ∀ ⦃R : Type u⦄ (S : Type u) [CommRing R] [CommRing S] [Algebra R S] (r : R) - [IsLocalization.Away r S], P (algebraMap R S) - -/-- A property `P` of ring homs satisfies `RingHom.StableUnderCompositionWithLocalizationAway` -if whenever `P` holds for `f` it also holds for the composition with -localization maps on the left and on the right. -/ -def RingHom.StableUnderCompositionWithLocalizationAway : Prop := - (∀ ⦃R S : Type u⦄ (T : Type u) [CommRing R] [CommRing S] [CommRing T] [Algebra S T] (s : S) - [IsLocalization.Away s T] (f : R →+* S), P f → P ((algebraMap S T).comp f)) ∧ - ∀ ⦃R : Type u⦄ (S : Type u) ⦃T : Type u⦄ [CommRing R] [CommRing S] [CommRing T] [Algebra R S] - (r : R) [IsLocalization.Away r S] (f : S →+* T), P f → P (f.comp (algebraMap R S)) - -/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpanTarget` -if `P` holds for `R →+* S` whenever there exists a finite set `{ r }` that spans `S` such that -`P` holds for `R →+* Sᵣ`. - -Note that this is equivalent to `RingHom.OfLocalizationSpanTarget` via -`RingHom.ofLocalizationSpanTarget_iff_finite`, but this is easier to prove. -/ -def RingHom.OfLocalizationFiniteSpanTarget : Prop := - ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Finset S) - (_ : Ideal.span (s : Set S) = ⊤) - (_ : ∀ r : s, P ((algebraMap S (Localization.Away (r : S))).comp f)), P f - -/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationSpanTarget` -if `P` holds for `R →+* S` whenever there exists a set `{ r }` that spans `S` such that -`P` holds for `R →+* Sᵣ`. - -Note that this is equivalent to `RingHom.OfLocalizationFiniteSpanTarget` via -`RingHom.ofLocalizationSpanTarget_iff_finite`, but this has less restrictions when applying. -/ -def RingHom.OfLocalizationSpanTarget : Prop := - ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Set S) (_ : Ideal.span s = ⊤) - (_ : ∀ r : s, P ((algebraMap S (Localization.Away (r : S))).comp f)), P f - -/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationPrime` -if `P` holds for `R` whenever `P` holds for `Rₘ` for all prime ideals `p`. -/ -def RingHom.OfLocalizationPrime : Prop := - ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S), - (∀ (J : Ideal S) (_ : J.IsPrime), P (Localization.localRingHom _ J f rfl)) → P f - -/-- A property of ring homs is local if it is preserved by localizations and compositions, and for -each `{ r }` that spans `S`, we have `P (R →+* S) ↔ ∀ r, P (R →+* Sᵣ)`. -/ -structure RingHom.PropertyIsLocal : Prop where - LocalizationPreserves : RingHom.LocalizationPreserves @P - OfLocalizationSpanTarget : RingHom.OfLocalizationSpanTarget @P - StableUnderCompositionWithLocalizationAway : RingHom.StableUnderCompositionWithLocalizationAway @P - -theorem RingHom.ofLocalizationSpan_iff_finite : - RingHom.OfLocalizationSpan @P ↔ RingHom.OfLocalizationFiniteSpan @P := by - delta RingHom.OfLocalizationSpan RingHom.OfLocalizationFiniteSpan - apply forall₅_congr - -- TODO: Using `refine` here breaks `resetI`. - intros - constructor - · intro h s; exact h s - · intro h s hs hs' - obtain ⟨s', h₁, h₂⟩ := (Ideal.span_eq_top_iff_finite s).mp hs - exact h s' h₂ fun x => hs' ⟨_, h₁ x.prop⟩ - -theorem RingHom.ofLocalizationSpanTarget_iff_finite : - RingHom.OfLocalizationSpanTarget @P ↔ RingHom.OfLocalizationFiniteSpanTarget @P := by - delta RingHom.OfLocalizationSpanTarget RingHom.OfLocalizationFiniteSpanTarget - apply forall₅_congr - -- TODO: Using `refine` here breaks `resetI`. - intros - constructor - · intro h s; exact h s - · intro h s hs hs' - obtain ⟨s', h₁, h₂⟩ := (Ideal.span_eq_top_iff_finite s).mp hs - exact h s' h₂ fun x => hs' ⟨_, h₁ x.prop⟩ - -theorem RingHom.HoldsForLocalizationAway.of_bijective - (H : RingHom.HoldsForLocalizationAway P) (hf : Function.Bijective f) : - P f := by - letI := f.toAlgebra - have := IsLocalization.at_units (.powers (1 : R)) (by simp) - have := IsLocalization.isLocalization_of_algEquiv (.powers (1 : R)) - (AlgEquiv.ofBijective (Algebra.ofId R S) hf) - exact H _ 1 - -variable {P f R' S'} - -lemma RingHom.StableUnderComposition.stableUnderCompositionWithLocalizationAway - (hPc : RingHom.StableUnderComposition P) (hPl : HoldsForLocalizationAway P) : - StableUnderCompositionWithLocalizationAway P := by - constructor - · introv _ hf - exact hPc _ _ hf (hPl T s) - · introv _ hf - exact hPc _ _ (hPl S r) hf - -lemma RingHom.HoldsForLocalizationAway.containsIdentities (hPl : HoldsForLocalizationAway P) : - ContainsIdentities P := by - introv R - exact hPl.of_bijective _ _ Function.bijective_id - -theorem RingHom.PropertyIsLocal.respectsIso (hP : RingHom.PropertyIsLocal @P) : - RingHom.RespectsIso @P := by - constructor - · intro R S T _ _ _ f e hf - letI := e.toRingHom.toAlgebra - have : IsLocalization.Away (1 : S) T := - IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective - exact hP.StableUnderCompositionWithLocalizationAway.left T (1 : S) f hf - · intro R S T _ _ _ f e hf - letI := e.toRingHom.toAlgebra - have : IsLocalization.Away (1 : R) S := - IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective - exact hP.StableUnderCompositionWithLocalizationAway.right S (1 : R) f hf - --- Almost all arguments are implicit since this is not intended to use mid-proof. -theorem RingHom.LocalizationPreserves.away (H : RingHom.LocalizationPreserves @P) (r : R) - [IsLocalization.Away r R'] [IsLocalization.Away (f r) S'] (hf : P f) : - P (IsLocalization.Away.map R' S' f r) := by - have : IsLocalization ((Submonoid.powers r).map f) S' := by rw [Submonoid.map_powers]; assumption - exact H f (Submonoid.powers r) R' S' hf - -lemma RingHom.PropertyIsLocal.HoldsForLocalizationAway (hP : RingHom.PropertyIsLocal @P) - (hPi : ContainsIdentities P) : - RingHom.HoldsForLocalizationAway @P := by - introv R _ - have : algebraMap R S = (algebraMap R S).comp (RingHom.id R) := by simp - rw [this] - apply (hP.StableUnderCompositionWithLocalizationAway).left S r - apply hPi - -theorem RingHom.PropertyIsLocal.ofLocalizationSpan (hP : RingHom.PropertyIsLocal @P) : - RingHom.OfLocalizationSpan @P := by - introv R hs hs' - apply_fun Ideal.map f at hs - rw [Ideal.map_span, Ideal.map_top] at hs - apply hP.OfLocalizationSpanTarget _ _ hs - rintro ⟨_, r, hr, rfl⟩ - rw [← IsLocalization.map_comp (M := Submonoid.powers r) (S := Localization.Away r) - (T := Submonoid.powers (f r))] - apply hP.StableUnderCompositionWithLocalizationAway.right _ r - exact hs' ⟨r, hr⟩ - -lemma RingHom.OfLocalizationSpanTarget.ofIsLocalization - (hP : RingHom.OfLocalizationSpanTarget P) (hP' : RingHom.RespectsIso P) - {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) (s : Set S) (hs : Ideal.span s = ⊤) - (hT : ∀ r : s, ∃ (T : Type u) (_ : CommRing T) (_ : Algebra S T) - (_ : IsLocalization.Away (r : S) T), P ((algebraMap S T).comp f)) : P f := by - apply hP _ s hs - intros r - obtain ⟨T, _, _, _, hT⟩ := hT r - convert hP'.1 _ - (Localization.algEquiv (R := S) (Submonoid.powers (r : S)) T).symm.toRingEquiv hT - rw [← RingHom.comp_assoc, RingEquiv.toRingHom_eq_coe, AlgEquiv.toRingEquiv_eq_coe, - AlgEquiv.toRingEquiv_toRingHom, Localization.coe_algEquiv_symm, IsLocalization.map_comp, - RingHom.comp_id] - -end RingHom - -end Properties - -section Ideal - -open scoped nonZeroDivisors - -/-- Let `I J : Ideal R`. If the localization of `I` at each maximal ideal `P` is included in -the localization of `J` at `P`, then `I ≤ J`. -/ -theorem Ideal.le_of_localization_maximal {I J : Ideal R} - (h : ∀ (P : Ideal R) (hP : P.IsMaximal), - Ideal.map (algebraMap R (Localization.AtPrime P)) I ≤ - Ideal.map (algebraMap R (Localization.AtPrime P)) J) : - I ≤ J := by - intro x hx - suffices J.colon (Ideal.span {x}) = ⊤ by - simpa using Submodule.mem_colon.mp - (show (1 : R) ∈ J.colon (Ideal.span {x}) from this.symm ▸ Submodule.mem_top) x - (Ideal.mem_span_singleton_self x) - refine Not.imp_symm (J.colon (Ideal.span {x})).exists_le_maximal ?_ - push_neg - intro P hP le - obtain ⟨⟨⟨a, ha⟩, ⟨s, hs⟩⟩, eq⟩ := - (IsLocalization.mem_map_algebraMap_iff P.primeCompl _).mp (h P hP (Ideal.mem_map_of_mem _ hx)) - rw [← _root_.map_mul, ← sub_eq_zero, ← map_sub] at eq - obtain ⟨⟨m, hm⟩, eq⟩ := (IsLocalization.map_eq_zero_iff P.primeCompl _ _).mp eq - refine hs ((hP.isPrime.mem_or_mem (le (Ideal.mem_colon_singleton.mpr ?_))).resolve_right hm) - simp only [Subtype.coe_mk, mul_sub, sub_eq_zero, mul_comm x s, mul_left_comm] at eq - simpa only [mul_assoc, eq] using J.mul_mem_left m ha - -/-- Let `I J : Ideal R`. If the localization of `I` at each maximal ideal `P` is equal to -the localization of `J` at `P`, then `I = J`. -/ -theorem Ideal.eq_of_localization_maximal {I J : Ideal R} - (h : ∀ (P : Ideal R) (_ : P.IsMaximal), - Ideal.map (algebraMap R (Localization.AtPrime P)) I = - Ideal.map (algebraMap R (Localization.AtPrime P)) J) : - I = J := - le_antisymm (Ideal.le_of_localization_maximal fun P hP => (h P hP).le) - (Ideal.le_of_localization_maximal fun P hP => (h P hP).ge) - -/-- An ideal is trivial if its localization at every maximal ideal is trivial. -/ -theorem ideal_eq_bot_of_localization' (I : Ideal R) - (h : ∀ (J : Ideal R) (hJ : J.IsMaximal), - Ideal.map (algebraMap R (Localization.AtPrime J)) I = ⊥) : - I = ⊥ := - Ideal.eq_of_localization_maximal fun P hP => by simpa using h P hP - --- TODO: This proof should work for all modules, once we have enough material on submodules of --- localized modules. -/-- An ideal is trivial if its localization at every maximal ideal is trivial. -/ -theorem ideal_eq_bot_of_localization (I : Ideal R) - (h : ∀ (J : Ideal R) (hJ : J.IsMaximal), - IsLocalization.coeSubmodule (Localization.AtPrime J) I = ⊥) : - I = ⊥ := - ideal_eq_bot_of_localization' _ fun P hP => - (Ideal.map_eq_bot_iff_le_ker _).mpr fun x hx => by - rw [RingHom.mem_ker, ← Submodule.mem_bot R, ← h P hP, IsLocalization.mem_coeSubmodule] - exact ⟨x, hx, rfl⟩ - -theorem eq_zero_of_localization (r : R) - (h : ∀ (J : Ideal R) (hJ : J.IsMaximal), algebraMap R (Localization.AtPrime J) r = 0) : - r = 0 := by - rw [← Ideal.span_singleton_eq_bot] - apply ideal_eq_bot_of_localization - intro J hJ - delta IsLocalization.coeSubmodule - erw [Submodule.map_span, Submodule.span_eq_bot] - rintro _ ⟨_, h', rfl⟩ - cases Set.mem_singleton_iff.mpr h' - exact h J hJ - -end Ideal - -section Reduced - -theorem localization_isReduced : LocalizationPreserves fun R hR => IsReduced R := by - introv R _ _ - constructor - rintro x ⟨_ | n, e⟩ - · simpa using congr_arg (· * x) e - obtain ⟨⟨y, m⟩, hx⟩ := IsLocalization.surj M x - dsimp only at hx - let hx' := congr_arg (· ^ n.succ) hx - simp only [mul_pow, e, zero_mul, ← RingHom.map_pow] at hx' - rw [← (algebraMap R S).map_zero] at hx' - obtain ⟨m', hm'⟩ := (IsLocalization.eq_iff_exists M S).mp hx' - apply_fun (· * (m' : R) ^ n) at hm' - simp only [mul_assoc, zero_mul, mul_zero] at hm' - rw [← mul_left_comm, ← pow_succ', ← mul_pow] at hm' - replace hm' := IsNilpotent.eq_zero ⟨_, hm'.symm⟩ - rw [← (IsLocalization.map_units S m).mul_left_inj, hx, zero_mul, - IsLocalization.map_eq_zero_iff M] - exact ⟨m', by rw [← hm', mul_comm]⟩ - -instance [IsReduced R] : IsReduced (Localization M) := - localization_isReduced M _ inferInstance - -theorem isReduced_ofLocalizationMaximal : OfLocalizationMaximal fun R hR => IsReduced R := by - introv R h - constructor - intro x hx - apply eq_zero_of_localization - intro J hJ - specialize h J hJ - exact (hx.map <| algebraMap R <| Localization.AtPrime J).eq_zero - -end Reduced - -section Surjective - -theorem localizationPreserves_surjective : - RingHom.LocalizationPreserves fun {R S} _ _ f => Function.Surjective f := by - introv R H x - obtain ⟨x, ⟨_, s, hs, rfl⟩, rfl⟩ := IsLocalization.mk'_surjective (M.map f) x - obtain ⟨y, rfl⟩ := H x - use IsLocalization.mk' R' y ⟨s, hs⟩ - rw [IsLocalization.map_mk'] - -theorem surjective_ofLocalizationSpan : - RingHom.OfLocalizationSpan fun {R S} _ _ f => Function.Surjective f := by - introv R e H - rw [← Set.range_iff_surjective, Set.eq_univ_iff_forall] - letI := f.toAlgebra - intro x - apply Submodule.mem_of_span_eq_top_of_smul_pow_mem - (LinearMap.range (Algebra.linearMap R S)) s e - intro r - obtain ⟨a, e'⟩ := H r (algebraMap _ _ x) - obtain ⟨b, ⟨_, n, rfl⟩, rfl⟩ := IsLocalization.mk'_surjective (Submonoid.powers (r : R)) a - erw [IsLocalization.map_mk'] at e' - rw [eq_comm, IsLocalization.eq_mk'_iff_mul_eq, Subtype.coe_mk, Subtype.coe_mk, ← map_mul] at e' - obtain ⟨⟨_, n', rfl⟩, e''⟩ := (IsLocalization.eq_iff_exists (Submonoid.powers (f r)) _).mp e' - dsimp only at e'' - rw [mul_comm x, ← mul_assoc, ← map_pow, ← map_mul, ← map_mul, ← pow_add] at e'' - exact ⟨n' + n, _, e''.symm⟩ - -/-- A surjective ring homomorphism `R →+* S` induces a surjective homomorphism `R_{f⁻¹(P)} →+* S_P` -for every prime ideal `P` of `S`. -/ -theorem surjective_localRingHom_of_surjective (h : Function.Surjective f) (P : Ideal S) - [P.IsPrime] : Function.Surjective (Localization.localRingHom (P.comap f) P f rfl) := - have : IsLocalization (Submonoid.map f (Ideal.comap f P).primeCompl) (Localization.AtPrime P) := - (Submonoid.map_comap_eq_of_surjective h P.primeCompl).symm ▸ Localization.isLocalization - localizationPreserves_surjective _ _ _ _ h - -lemma surjective_respectsIso : RingHom.RespectsIso (fun f ↦ Function.Surjective f) := by - apply RingHom.StableUnderComposition.respectsIso - · intro R S T _ _ _ f g hf hg - simp only [RingHom.coe_comp] - exact Function.Surjective.comp hg hf - · intro R S _ _ e - exact EquivLike.surjective e - -end Surjective - -section Finite - -lemma Module.Finite_of_isLocalization (R S Rₚ Sₚ) [CommSemiring R] [CommRing S] [CommRing Rₚ] - [CommRing Sₚ] [Algebra R S] [Algebra R Rₚ] [Algebra R Sₚ] [Algebra S Sₚ] [Algebra Rₚ Sₚ] - [IsScalarTower R S Sₚ] [IsScalarTower R Rₚ Sₚ] (M : Submonoid R) [IsLocalization M Rₚ] - [IsLocalization (Algebra.algebraMapSubmonoid S M) Sₚ] [hRS : Module.Finite R S] : - Module.Finite Rₚ Sₚ := by - classical - have : algebraMap Rₚ Sₚ = IsLocalization.map (T := Algebra.algebraMapSubmonoid S M) Sₚ - (algebraMap R S) (Submonoid.le_comap_map M) := by - apply IsLocalization.ringHom_ext M - simp only [IsLocalization.map_comp, ← IsScalarTower.algebraMap_eq] - -- We claim that if `S` is generated by `T` as an `R`-module, - -- then `S'` is generated by `T` as an `R'`-module. - obtain ⟨T, hT⟩ := hRS - use T.image (algebraMap S Sₚ) - rw [eq_top_iff] - rintro x - - -- By the hypotheses, for each `x : S'`, we have `x = y / (f r)` for some `y : S` and `r : M`. - -- Since `S` is generated by `T`, the image of `y` should fall in the span of the image of `T`. - obtain ⟨y, ⟨_, ⟨r, hr, rfl⟩⟩, rfl⟩ := - IsLocalization.mk'_surjective (Algebra.algebraMapSubmonoid S M) x - rw [IsLocalization.mk'_eq_mul_mk'_one, mul_comm, Finset.coe_image] - have hy : y ∈ Submodule.span R ↑T := by rw [hT]; trivial - replace hy : algebraMap S Sₚ y ∈ Submodule.map (IsScalarTower.toAlgHom R S Sₚ).toLinearMap - (Submodule.span R (T : Set S)) := Submodule.mem_map_of_mem --- -- Note: #8386 had to specify the value of `f` below - (f := (IsScalarTower.toAlgHom R S Sₚ).toLinearMap) hy - rw [Submodule.map_span (IsScalarTower.toAlgHom R S Sₚ).toLinearMap T] at hy - have H : Submodule.span R (algebraMap S Sₚ '' T) ≤ - (Submodule.span Rₚ (algebraMap S Sₚ '' T)).restrictScalars R := by - rw [Submodule.span_le]; exact Submodule.subset_span - -- Now, since `y ∈ span T`, and `(f r)⁻¹ ∈ R'`, `x / (f r)` is in `span T` as well. - convert (Submodule.span Rₚ (algebraMap S Sₚ '' T)).smul_mem - (IsLocalization.mk' Rₚ (1 : R) ⟨r, hr⟩) (H hy) using 1 - rw [Algebra.smul_def, this, IsLocalization.map_mk', map_one] - -/-- If `S` is a finite `R`-algebra, then `S' = M⁻¹S` is a finite `R' = M⁻¹R`-algebra. -/ -theorem localization_finite : RingHom.LocalizationPreserves @RingHom.Finite := by - introv R hf - letI := f.toAlgebra - letI := ((algebraMap S S').comp f).toAlgebra - let f' : R' →+* S' := IsLocalization.map S' f (Submonoid.le_comap_map M) - letI := f'.toAlgebra - have : IsScalarTower R R' S' := IsScalarTower.of_algebraMap_eq' - (IsLocalization.map_comp M.le_comap_map).symm - have : IsScalarTower R S S' := IsScalarTower.of_algebraMap_eq' rfl - have : IsLocalization (Algebra.algebraMapSubmonoid S M) S' := by - rwa [Algebra.algebraMapSubmonoid, RingHom.algebraMap_toAlgebra] - have : Module.Finite R S := hf - apply Module.Finite_of_isLocalization R S R' S' M - -theorem localization_away_map_finite (r : R) [IsLocalization.Away r R'] - [IsLocalization.Away (f r) S'] (hf : f.Finite) : (IsLocalization.Away.map R' S' f r).Finite := - localization_finite.away r hf - -/-- Let `S` be an `R`-algebra, `M` a submonoid of `R`, and `S' = M⁻¹S`. -If the image of some `x : S` falls in the span of some finite `s ⊆ S'` over `R`, -then there exists some `m : M` such that `m • x` falls in the -span of `IsLocalization.finsetIntegerMultiple _ s` over `R`. --/ -theorem IsLocalization.smul_mem_finsetIntegerMultiple_span [Algebra R S] [Algebra R S'] - [IsScalarTower R S S'] [IsLocalization (M.map (algebraMap R S)) S'] (x : S) (s : Finset S') - (hx : algebraMap S S' x ∈ Submodule.span R (s : Set S')) : - ∃ m : M, m • x ∈ - Submodule.span R - (IsLocalization.finsetIntegerMultiple (M.map (algebraMap R S)) s : Set S) := by - let g : S →ₐ[R] S' := - AlgHom.mk' (algebraMap S S') fun c x => by simp [Algebra.algebraMap_eq_smul_one] - -- We first obtain the `y' ∈ M` such that `s' = y' • s` is falls in the image of `S` in `S'`. - let y := IsLocalization.commonDenomOfFinset (M.map (algebraMap R S)) s - have hx₁ : (y : S) • (s : Set S') = g '' _ := - (IsLocalization.finsetIntegerMultiple_image _ s).symm - obtain ⟨y', hy', e : algebraMap R S y' = y⟩ := y.prop - have : algebraMap R S y' • (s : Set S') = y' • (s : Set S') := by - simp_rw [Algebra.algebraMap_eq_smul_one, smul_assoc, one_smul] - rw [← e, this] at hx₁ - replace hx₁ := congr_arg (Submodule.span R) hx₁ - rw [Submodule.span_smul] at hx₁ - replace hx : _ ∈ y' • Submodule.span R (s : Set S') := Set.smul_mem_smul_set hx - rw [hx₁] at hx - erw [← _root_.map_smul g, ← Submodule.map_span (g : S →ₗ[R] S')] at hx - -- Since `x` falls in the span of `s` in `S'`, `y' • x : S` falls in the span of `s'` in `S'`. - -- That is, there exists some `x' : S` in the span of `s'` in `S` and `x' = y' • x` in `S'`. - -- Thus `a • (y' • x) = a • x' ∈ span s'` in `S` for some `a ∈ M`. - obtain ⟨x', hx', hx'' : algebraMap _ _ _ = _⟩ := hx - obtain ⟨⟨_, a, ha₁, rfl⟩, ha₂⟩ := - (IsLocalization.eq_iff_exists (M.map (algebraMap R S)) S').mp hx'' - use (⟨a, ha₁⟩ : M) * (⟨y', hy'⟩ : M) - convert (Submodule.span R - (IsLocalization.finsetIntegerMultiple (Submonoid.map (algebraMap R S) M) s : Set S)).smul_mem - a hx' using 1 - convert ha₂.symm using 1 - · rw [Subtype.coe_mk, Submonoid.smul_def, Submonoid.coe_mul, ← smul_smul] - exact Algebra.smul_def _ _ - · exact Algebra.smul_def _ _ - -/-- If `M` is an `R' = S⁻¹R` module, and `x ∈ span R' s`, -then `t • x ∈ span R s` for some `t : S`. -/ -theorem multiple_mem_span_of_mem_localization_span - {N : Type*} [AddCommMonoid N] [Module R N] [Module R' N] - [IsScalarTower R R' N] [IsLocalization M R'] (s : Set N) (x : N) - (hx : x ∈ Submodule.span R' s) : ∃ (t : M), t • x ∈ Submodule.span R s := by - classical - obtain ⟨s', hss', hs'⟩ := Submodule.mem_span_finite_of_mem_span hx - rsuffices ⟨t, ht⟩ : ∃ t : M, t • x ∈ Submodule.span R (s' : Set N) - · exact ⟨t, Submodule.span_mono hss' ht⟩ - clear hx hss' s - induction s' using Finset.induction_on generalizing x - · use 1; simpa using hs' - rename_i a s _ hs - simp only [Finset.coe_insert, Finset.image_insert, Finset.coe_image, Subtype.coe_mk, - Submodule.mem_span_insert] at hs' ⊢ - rcases hs' with ⟨y, z, hz, rfl⟩ - rcases IsLocalization.surj M y with ⟨⟨y', s'⟩, e⟩ - apply congrArg (fun x ↦ x • a) at e - simp only [algebraMap_smul] at e - rcases hs _ hz with ⟨t, ht⟩ - refine ⟨t * s', t * y', _, (Submodule.span R (s : Set N)).smul_mem s' ht, ?_⟩ - rw [smul_add, ← smul_smul, mul_comm, ← smul_smul, ← smul_smul, ← e, mul_comm, ← Algebra.smul_def] - simp - rfl - -/-- If `S` is an `R' = M⁻¹R` algebra, and `x ∈ adjoin R' s`, -then `t • x ∈ adjoin R s` for some `t : M`. -/ -theorem multiple_mem_adjoin_of_mem_localization_adjoin [Algebra R' S] [Algebra R S] - [IsScalarTower R R' S] [IsLocalization M R'] (s : Set S) (x : S) - (hx : x ∈ Algebra.adjoin R' s) : ∃ t : M, t • x ∈ Algebra.adjoin R s := by - change ∃ t : M, t • x ∈ Subalgebra.toSubmodule (Algebra.adjoin R s) - change x ∈ Subalgebra.toSubmodule (Algebra.adjoin R' s) at hx - simp_rw [Algebra.adjoin_eq_span] at hx ⊢ - exact multiple_mem_span_of_mem_localization_span M R' _ _ hx - -theorem finite_ofLocalizationSpan : RingHom.OfLocalizationSpan @RingHom.Finite := by - rw [RingHom.ofLocalizationSpan_iff_finite] - introv R hs H - -- We first setup the instances - letI := f.toAlgebra - letI := fun r : s => (Localization.awayMap f r).toAlgebra - have : ∀ r : s, - IsLocalization ((Submonoid.powers (r : R)).map (algebraMap R S)) (Localization.Away (f r)) := - by intro r; rw [Submonoid.map_powers]; exact Localization.isLocalization - haveI : ∀ r : s, IsScalarTower R (Localization.Away (r : R)) (Localization.Away (f r)) := - fun r => IsScalarTower.of_algebraMap_eq' - (IsLocalization.map_comp (Submonoid.powers (r : R)).le_comap_map).symm - -- By the hypothesis, we may find a finite generating set for each `Sᵣ`. This set can then be - -- lifted into `R` by multiplying a sufficiently large power of `r`. I claim that the union of - -- these generates `S`. - constructor - replace H := fun r => (H r).1 - choose s₁ s₂ using H - let sf := fun x : s => IsLocalization.finsetIntegerMultiple (Submonoid.powers (f x)) (s₁ x) - use s.attach.biUnion sf - rw [Submodule.span_attach_biUnion, eq_top_iff] - -- It suffices to show that `r ^ n • x ∈ span T` for each `r : s`, since `{ r ^ n }` spans `R`. - -- This then follows from the fact that each `x : R` is a linear combination of the generating set - -- of `Sᵣ`. By multiplying a sufficiently large power of `r`, we can cancel out the `r`s in the - -- denominators of both the generating set and the coefficients. - rintro x - - apply Submodule.mem_of_span_eq_top_of_smul_pow_mem _ (s : Set R) hs _ _ - intro r - obtain ⟨⟨_, n₁, rfl⟩, hn₁⟩ := - multiple_mem_span_of_mem_localization_span (Submonoid.powers (r : R)) - (Localization.Away (r : R)) (s₁ r : Set (Localization.Away (f r))) (algebraMap S _ x) - (by rw [s₂ r]; trivial) - dsimp only at hn₁ - rw [Submonoid.smul_def, Algebra.smul_def, IsScalarTower.algebraMap_apply R S, ← map_mul] at hn₁ - obtain ⟨⟨_, n₂, rfl⟩, hn₂⟩ := - IsLocalization.smul_mem_finsetIntegerMultiple_span (Submonoid.powers (r : R)) - (Localization.Away (f r)) _ (s₁ r) hn₁ - rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, ← pow_add] at hn₂ - simp_rw [Submonoid.map_powers] at hn₂ - use n₂ + n₁ - exact le_iSup (fun x : s => Submodule.span R (sf x : Set S)) r hn₂ - -end Finite - -section FiniteType - -theorem localization_finiteType : RingHom.LocalizationPreserves @RingHom.FiniteType := by - introv R hf - -- mirrors the proof of `localization_map_finite` - letI := f.toAlgebra - letI := ((algebraMap S S').comp f).toAlgebra - let f' : R' →+* S' := IsLocalization.map S' f (Submonoid.le_comap_map M) - letI := f'.toAlgebra - haveI : IsScalarTower R R' S' := - IsScalarTower.of_algebraMap_eq' (IsLocalization.map_comp M.le_comap_map).symm - let fₐ : S →ₐ[R] S' := AlgHom.mk' (algebraMap S S') fun c x => RingHom.map_mul _ _ _ - obtain ⟨T, hT⟩ := id hf - use T.image (algebraMap S S') - rw [eq_top_iff] - rintro x - - obtain ⟨y, ⟨_, ⟨r, hr, rfl⟩⟩, rfl⟩ := IsLocalization.mk'_surjective (M.map f) x - rw [IsLocalization.mk'_eq_mul_mk'_one, mul_comm, Finset.coe_image] - have hy : y ∈ Algebra.adjoin R (T : Set S) := by rw [hT]; trivial - replace hy : algebraMap S S' y ∈ (Algebra.adjoin R (T : Set S)).map fₐ := - Subalgebra.mem_map.mpr ⟨_, hy, rfl⟩ - rw [fₐ.map_adjoin T] at hy - have H : Algebra.adjoin R (algebraMap S S' '' T) ≤ - (Algebra.adjoin R' (algebraMap S S' '' T)).restrictScalars R := by - rw [Algebra.adjoin_le_iff]; exact Algebra.subset_adjoin - convert (Algebra.adjoin R' (algebraMap S S' '' T)).smul_mem (H hy) - (IsLocalization.mk' R' (1 : R) ⟨r, hr⟩) using 1 - rw [Algebra.smul_def] - erw [IsLocalization.map_mk' M.le_comap_map] - rw [map_one] - -theorem localization_away_map_finiteType (r : R) [IsLocalization.Away r R'] - [IsLocalization.Away (f r) S'] (hf : f.FiniteType) : - (IsLocalization.Away.map R' S' f r).FiniteType := - localization_finiteType.away r hf - -variable {S'} - -/-- Let `S` be an `R`-algebra, `M` a submonoid of `S`, `S' = M⁻¹S`. -Suppose the image of some `x : S` falls in the adjoin of some finite `s ⊆ S'` over `R`, -and `A` is an `R`-subalgebra of `S` containing both `M` and the numerators of `s`. -Then, there exists some `m : M` such that `m • x` falls in `A`. --/ -theorem IsLocalization.exists_smul_mem_of_mem_adjoin [Algebra R S] [Algebra R S'] - [IsScalarTower R S S'] (M : Submonoid S) [IsLocalization M S'] (x : S) (s : Finset S') - (A : Subalgebra R S) (hA₁ : (IsLocalization.finsetIntegerMultiple M s : Set S) ⊆ A) - (hA₂ : M ≤ A.toSubmonoid) (hx : algebraMap S S' x ∈ Algebra.adjoin R (s : Set S')) : - ∃ m : M, m • x ∈ A := by - let g : S →ₐ[R] S' := IsScalarTower.toAlgHom R S S' - let y := IsLocalization.commonDenomOfFinset M s - have hx₁ : (y : S) • (s : Set S') = g '' _ := - (IsLocalization.finsetIntegerMultiple_image _ s).symm - obtain ⟨n, hn⟩ := - Algebra.pow_smul_mem_of_smul_subset_of_mem_adjoin (y : S) (s : Set S') (A.map g) - (by rw [hx₁]; exact Set.image_subset _ hA₁) hx (Set.mem_image_of_mem _ (hA₂ y.2)) - obtain ⟨x', hx', hx''⟩ := hn n (le_of_eq rfl) - rw [Algebra.smul_def, ← _root_.map_mul] at hx'' - obtain ⟨a, ha₂⟩ := (IsLocalization.eq_iff_exists M S').mp hx'' - use a * y ^ n - convert A.mul_mem hx' (hA₂ a.prop) using 1 - rw [Submonoid.smul_def, smul_eq_mul, Submonoid.coe_mul, SubmonoidClass.coe_pow, mul_assoc, ← ha₂, - mul_comm] - -/-- Let `S` be an `R`-algebra, `M` a submonoid of `R`, and `S' = M⁻¹S`. -If the image of some `x : S` falls in the adjoin of some finite `s ⊆ S'` over `R`, -then there exists some `m : M` such that `m • x` falls in the -adjoin of `IsLocalization.finsetIntegerMultiple _ s` over `R`. --/ -theorem IsLocalization.lift_mem_adjoin_finsetIntegerMultiple [Algebra R S] [Algebra R S'] - [IsScalarTower R S S'] [IsLocalization (M.map (algebraMap R S)) S'] (x : S) (s : Finset S') - (hx : algebraMap S S' x ∈ Algebra.adjoin R (s : Set S')) : - ∃ m : M, m • x ∈ - Algebra.adjoin R - (IsLocalization.finsetIntegerMultiple (M.map (algebraMap R S)) s : Set S) := by - obtain ⟨⟨_, a, ha, rfl⟩, e⟩ := - IsLocalization.exists_smul_mem_of_mem_adjoin (M.map (algebraMap R S)) x s (Algebra.adjoin R _) - Algebra.subset_adjoin (by rintro _ ⟨a, _, rfl⟩; exact Subalgebra.algebraMap_mem _ a) hx - refine ⟨⟨a, ha⟩, ?_⟩ - simpa only [Submonoid.smul_def, algebraMap_smul] using e - -theorem finiteType_ofLocalizationSpan : RingHom.OfLocalizationSpan @RingHom.FiniteType := by - rw [RingHom.ofLocalizationSpan_iff_finite] - introv R hs H - -- mirrors the proof of `finite_ofLocalizationSpan` - letI := f.toAlgebra - letI := fun r : s => (Localization.awayMap f r).toAlgebra - have : ∀ r : s, - IsLocalization ((Submonoid.powers (r : R)).map (algebraMap R S)) (Localization.Away (f r)) := - by intro r; rw [Submonoid.map_powers]; exact Localization.isLocalization - haveI : ∀ r : s, IsScalarTower R (Localization.Away (r : R)) (Localization.Away (f r)) := - fun r => IsScalarTower.of_algebraMap_eq' - (IsLocalization.map_comp (Submonoid.powers (r : R)).le_comap_map).symm - constructor - replace H := fun r => (H r).1 - choose s₁ s₂ using H - let sf := fun x : s => IsLocalization.finsetIntegerMultiple (Submonoid.powers (f x)) (s₁ x) - use s.attach.biUnion sf - convert (Algebra.adjoin_attach_biUnion (R := R) sf).trans _ - rw [eq_top_iff] - rintro x - - apply (⨆ x : s, Algebra.adjoin R (sf x : Set S)).toSubmodule.mem_of_span_eq_top_of_smul_pow_mem - _ hs _ _ - intro r - obtain ⟨⟨_, n₁, rfl⟩, hn₁⟩ := - multiple_mem_adjoin_of_mem_localization_adjoin (Submonoid.powers (r : R)) - (Localization.Away (r : R)) (s₁ r : Set (Localization.Away (f r))) - (algebraMap S (Localization.Away (f r)) x) (by rw [s₂ r]; trivial) - rw [Submonoid.smul_def, Algebra.smul_def, IsScalarTower.algebraMap_apply R S, ← map_mul] at hn₁ - obtain ⟨⟨_, n₂, rfl⟩, hn₂⟩ := - IsLocalization.lift_mem_adjoin_finsetIntegerMultiple (Submonoid.powers (r : R)) _ (s₁ r) hn₁ - rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, ← pow_add] at hn₂ - simp_rw [Submonoid.map_powers] at hn₂ - use n₂ + n₁ - exact le_iSup (fun x : s => Algebra.adjoin R (sf x : Set S)) r hn₂ - -end FiniteType - -section IsIntegallyClosed - -/-- `IsIntegrallyClosed` is a local property. -/ -theorem isIntegrallyClosed_ofLocalizationMaximal : - OfLocalizationMaximal fun R _ ↦ ([IsDomain R] → IsIntegrallyClosed R) := - fun _ _ h _ ↦ IsIntegrallyClosed.of_localization_maximal fun p _ hpm ↦ h p hpm - -end IsIntegallyClosed diff --git a/Mathlib/RingTheory/LocalProperties/Basic.lean b/Mathlib/RingTheory/LocalProperties/Basic.lean new file mode 100644 index 0000000000000..0141196dfed77 --- /dev/null +++ b/Mathlib/RingTheory/LocalProperties/Basic.lean @@ -0,0 +1,332 @@ +/- +Copyright (c) 2021 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.Localization.AtPrime +import Mathlib.RingTheory.Localization.Submodule +import Mathlib.RingTheory.RingHomProperties + +/-! +# Local properties of commutative rings + +In this file, we define local properties in general. + +## Naming Conventions + +* `localization_P` : `P` holds for `S⁻¹R` if `P` holds for `R`. +* `P_of_localization_maximal` : `P` holds for `R` if `P` holds for `Rₘ` for all maximal `m`. +* `P_of_localization_prime` : `P` holds for `R` if `P` holds for `Rₘ` for all prime `m`. +* `P_ofLocalizationSpan` : `P` holds for `R` if given a spanning set `{fᵢ}`, `P` holds for all + `R_{fᵢ}`. + +## Main definitions + +* `LocalizationPreserves` : A property `P` of comm rings is said to be preserved by localization + if `P` holds for `M⁻¹R` whenever `P` holds for `R`. +* `OfLocalizationMaximal` : A property `P` of comm rings satisfies `OfLocalizationMaximal` + if `P` holds for `R` whenever `P` holds for `Rₘ` for all maximal ideal `m`. +* `RingHom.LocalizationPreserves` : A property `P` of ring homs is said to be preserved by + localization if `P` holds for `M⁻¹R →+* M⁻¹S` whenever `P` holds for `R →+* S`. +* `RingHom.OfLocalizationSpan` : A property `P` of ring homs satisfies + `RingHom.OfLocalizationSpan` if `P` holds for `R →+* S` whenever there exists a + set `{ r }` that spans `R` such that `P` holds for `Rᵣ →+* Sᵣ`. + +## Main results + +* The triviality of an ideal or an element: + `ideal_eq_bot_of_localization`, `eq_zero_of_localization` + +-/ + +open scoped Pointwise Classical + +universe u + +variable {R S : Type u} [CommRing R] [CommRing S] (M : Submonoid R) (f : R →+* S) +variable (N : Submonoid S) (R' S' : Type u) [CommRing R'] [CommRing S'] +variable [Algebra R R'] [Algebra S S'] + +section Properties + +section CommRing + +variable (P : ∀ (R : Type u) [CommRing R], Prop) + +/-- A property `P` of comm rings is said to be preserved by localization + if `P` holds for `M⁻¹R` whenever `P` holds for `R`. -/ +def LocalizationPreserves : Prop := + ∀ {R : Type u} [hR : CommRing R] (M : Submonoid R) (S : Type u) [hS : CommRing S] [Algebra R S] + [IsLocalization M S], @P R hR → @P S hS + +/-- A property `P` of comm rings satisfies `OfLocalizationMaximal` + if `P` holds for `R` whenever `P` holds for `Rₘ` for all maximal ideal `m`. -/ +def OfLocalizationMaximal : Prop := + ∀ (R : Type u) [CommRing R], + (∀ (J : Ideal R) (_ : J.IsMaximal), P (Localization.AtPrime J)) → P R + +end CommRing + +section RingHom + +variable (P : ∀ {R S : Type u} [CommRing R] [CommRing S] (_ : R →+* S), Prop) + +/-- A property `P` of ring homs is said to contain identities if `P` holds +for the identity homomorphism of every ring. -/ +def RingHom.ContainsIdentities := ∀ (R : Type u) [CommRing R], P (RingHom.id R) + +/-- A property `P` of ring homs is said to be preserved by localization + if `P` holds for `M⁻¹R →+* M⁻¹S` whenever `P` holds for `R →+* S`. -/ +def RingHom.LocalizationPreserves := + ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (M : Submonoid R) (R' S' : Type u) + [CommRing R'] [CommRing S'] [Algebra R R'] [Algebra S S'] [IsLocalization M R'] + [IsLocalization (M.map f) S'], + P f → P (IsLocalization.map S' f (Submonoid.le_comap_map M) : R' →+* S') + +/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpan` +if `P` holds for `R →+* S` whenever there exists a finite set `{ r }` that spans `R` such that +`P` holds for `Rᵣ →+* Sᵣ`. + +Note that this is equivalent to `RingHom.OfLocalizationSpan` via +`RingHom.ofLocalizationSpan_iff_finite`, but this is easier to prove. -/ +def RingHom.OfLocalizationFiniteSpan := + ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Finset R) + (_ : Ideal.span (s : Set R) = ⊤) (_ : ∀ r : s, P (Localization.awayMap f r)), P f + +/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpan` +if `P` holds for `R →+* S` whenever there exists a set `{ r }` that spans `R` such that +`P` holds for `Rᵣ →+* Sᵣ`. + +Note that this is equivalent to `RingHom.OfLocalizationFiniteSpan` via +`RingHom.ofLocalizationSpan_iff_finite`, but this has less restrictions when applying. -/ +def RingHom.OfLocalizationSpan := + ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Set R) (_ : Ideal.span s = ⊤) + (_ : ∀ r : s, P (Localization.awayMap f r)), P f + +/-- A property `P` of ring homs satisfies `RingHom.HoldsForLocalizationAway` + if `P` holds for each localization map `R →+* Rᵣ`. -/ +def RingHom.HoldsForLocalizationAway : Prop := + ∀ ⦃R : Type u⦄ (S : Type u) [CommRing R] [CommRing S] [Algebra R S] (r : R) + [IsLocalization.Away r S], P (algebraMap R S) + +/-- A property `P` of ring homs satisfies `RingHom.StableUnderCompositionWithLocalizationAway` +if whenever `P` holds for `f` it also holds for the composition with +localization maps on the left and on the right. -/ +def RingHom.StableUnderCompositionWithLocalizationAway : Prop := + (∀ ⦃R S : Type u⦄ (T : Type u) [CommRing R] [CommRing S] [CommRing T] [Algebra S T] (s : S) + [IsLocalization.Away s T] (f : R →+* S), P f → P ((algebraMap S T).comp f)) ∧ + ∀ ⦃R : Type u⦄ (S : Type u) ⦃T : Type u⦄ [CommRing R] [CommRing S] [CommRing T] [Algebra R S] + (r : R) [IsLocalization.Away r S] (f : S →+* T), P f → P (f.comp (algebraMap R S)) + +/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationFiniteSpanTarget` +if `P` holds for `R →+* S` whenever there exists a finite set `{ r }` that spans `S` such that +`P` holds for `R →+* Sᵣ`. + +Note that this is equivalent to `RingHom.OfLocalizationSpanTarget` via +`RingHom.ofLocalizationSpanTarget_iff_finite`, but this is easier to prove. -/ +def RingHom.OfLocalizationFiniteSpanTarget : Prop := + ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Finset S) + (_ : Ideal.span (s : Set S) = ⊤) + (_ : ∀ r : s, P ((algebraMap S (Localization.Away (r : S))).comp f)), P f + +/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationSpanTarget` +if `P` holds for `R →+* S` whenever there exists a set `{ r }` that spans `S` such that +`P` holds for `R →+* Sᵣ`. + +Note that this is equivalent to `RingHom.OfLocalizationFiniteSpanTarget` via +`RingHom.ofLocalizationSpanTarget_iff_finite`, but this has less restrictions when applying. -/ +def RingHom.OfLocalizationSpanTarget : Prop := + ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S) (s : Set S) (_ : Ideal.span s = ⊤) + (_ : ∀ r : s, P ((algebraMap S (Localization.Away (r : S))).comp f)), P f + +/-- A property `P` of ring homs satisfies `RingHom.OfLocalizationPrime` +if `P` holds for `R` whenever `P` holds for `Rₘ` for all prime ideals `p`. -/ +def RingHom.OfLocalizationPrime : Prop := + ∀ ⦃R S : Type u⦄ [CommRing R] [CommRing S] (f : R →+* S), + (∀ (J : Ideal S) (_ : J.IsPrime), P (Localization.localRingHom _ J f rfl)) → P f + +/-- A property of ring homs is local if it is preserved by localizations and compositions, and for +each `{ r }` that spans `S`, we have `P (R →+* S) ↔ ∀ r, P (R →+* Sᵣ)`. -/ +structure RingHom.PropertyIsLocal : Prop where + LocalizationPreserves : RingHom.LocalizationPreserves @P + OfLocalizationSpanTarget : RingHom.OfLocalizationSpanTarget @P + StableUnderCompositionWithLocalizationAway : RingHom.StableUnderCompositionWithLocalizationAway @P + +theorem RingHom.ofLocalizationSpan_iff_finite : + RingHom.OfLocalizationSpan @P ↔ RingHom.OfLocalizationFiniteSpan @P := by + delta RingHom.OfLocalizationSpan RingHom.OfLocalizationFiniteSpan + apply forall₅_congr + -- TODO: Using `refine` here breaks `resetI`. + intros + constructor + · intro h s; exact h s + · intro h s hs hs' + obtain ⟨s', h₁, h₂⟩ := (Ideal.span_eq_top_iff_finite s).mp hs + exact h s' h₂ fun x => hs' ⟨_, h₁ x.prop⟩ + +theorem RingHom.ofLocalizationSpanTarget_iff_finite : + RingHom.OfLocalizationSpanTarget @P ↔ RingHom.OfLocalizationFiniteSpanTarget @P := by + delta RingHom.OfLocalizationSpanTarget RingHom.OfLocalizationFiniteSpanTarget + apply forall₅_congr + -- TODO: Using `refine` here breaks `resetI`. + intros + constructor + · intro h s; exact h s + · intro h s hs hs' + obtain ⟨s', h₁, h₂⟩ := (Ideal.span_eq_top_iff_finite s).mp hs + exact h s' h₂ fun x => hs' ⟨_, h₁ x.prop⟩ + +theorem RingHom.HoldsForLocalizationAway.of_bijective + (H : RingHom.HoldsForLocalizationAway P) (hf : Function.Bijective f) : + P f := by + letI := f.toAlgebra + have := IsLocalization.at_units (.powers (1 : R)) (by simp) + have := IsLocalization.isLocalization_of_algEquiv (.powers (1 : R)) + (AlgEquiv.ofBijective (Algebra.ofId R S) hf) + exact H _ 1 + +variable {P f R' S'} + +lemma RingHom.StableUnderComposition.stableUnderCompositionWithLocalizationAway + (hPc : RingHom.StableUnderComposition P) (hPl : HoldsForLocalizationAway P) : + StableUnderCompositionWithLocalizationAway P := by + constructor + · introv _ hf + exact hPc _ _ hf (hPl T s) + · introv _ hf + exact hPc _ _ (hPl S r) hf + +lemma RingHom.HoldsForLocalizationAway.containsIdentities (hPl : HoldsForLocalizationAway P) : + ContainsIdentities P := by + introv R + exact hPl.of_bijective _ _ Function.bijective_id + +theorem RingHom.PropertyIsLocal.respectsIso (hP : RingHom.PropertyIsLocal @P) : + RingHom.RespectsIso @P := by + constructor + · intro R S T _ _ _ f e hf + letI := e.toRingHom.toAlgebra + have : IsLocalization.Away (1 : S) T := + IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective + exact hP.StableUnderCompositionWithLocalizationAway.left T (1 : S) f hf + · intro R S T _ _ _ f e hf + letI := e.toRingHom.toAlgebra + have : IsLocalization.Away (1 : R) S := + IsLocalization.away_of_isUnit_of_bijective _ isUnit_one e.bijective + exact hP.StableUnderCompositionWithLocalizationAway.right S (1 : R) f hf + +-- Almost all arguments are implicit since this is not intended to use mid-proof. +theorem RingHom.LocalizationPreserves.away (H : RingHom.LocalizationPreserves @P) (r : R) + [IsLocalization.Away r R'] [IsLocalization.Away (f r) S'] (hf : P f) : + P (IsLocalization.Away.map R' S' f r) := by + have : IsLocalization ((Submonoid.powers r).map f) S' := by rw [Submonoid.map_powers]; assumption + exact H f (Submonoid.powers r) R' S' hf + +lemma RingHom.PropertyIsLocal.HoldsForLocalizationAway (hP : RingHom.PropertyIsLocal @P) + (hPi : ContainsIdentities P) : + RingHom.HoldsForLocalizationAway @P := by + introv R _ + have : algebraMap R S = (algebraMap R S).comp (RingHom.id R) := by simp + rw [this] + apply (hP.StableUnderCompositionWithLocalizationAway).left S r + apply hPi + +theorem RingHom.PropertyIsLocal.ofLocalizationSpan (hP : RingHom.PropertyIsLocal @P) : + RingHom.OfLocalizationSpan @P := by + introv R hs hs' + apply_fun Ideal.map f at hs + rw [Ideal.map_span, Ideal.map_top] at hs + apply hP.OfLocalizationSpanTarget _ _ hs + rintro ⟨_, r, hr, rfl⟩ + rw [← IsLocalization.map_comp (M := Submonoid.powers r) (S := Localization.Away r) + (T := Submonoid.powers (f r))] + apply hP.StableUnderCompositionWithLocalizationAway.right _ r + exact hs' ⟨r, hr⟩ + +lemma RingHom.OfLocalizationSpanTarget.ofIsLocalization + (hP : RingHom.OfLocalizationSpanTarget P) (hP' : RingHom.RespectsIso P) + {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) (s : Set S) (hs : Ideal.span s = ⊤) + (hT : ∀ r : s, ∃ (T : Type u) (_ : CommRing T) (_ : Algebra S T) + (_ : IsLocalization.Away (r : S) T), P ((algebraMap S T).comp f)) : P f := by + apply hP _ s hs + intros r + obtain ⟨T, _, _, _, hT⟩ := hT r + convert hP'.1 _ + (Localization.algEquiv (R := S) (Submonoid.powers (r : S)) T).symm.toRingEquiv hT + rw [← RingHom.comp_assoc, RingEquiv.toRingHom_eq_coe, AlgEquiv.toRingEquiv_eq_coe, + AlgEquiv.toRingEquiv_toRingHom, Localization.coe_algEquiv_symm, IsLocalization.map_comp, + RingHom.comp_id] + +end RingHom + +end Properties + +section Ideal + +open scoped nonZeroDivisors + +/-- Let `I J : Ideal R`. If the localization of `I` at each maximal ideal `P` is included in +the localization of `J` at `P`, then `I ≤ J`. -/ +theorem Ideal.le_of_localization_maximal {I J : Ideal R} + (h : ∀ (P : Ideal R) (hP : P.IsMaximal), + Ideal.map (algebraMap R (Localization.AtPrime P)) I ≤ + Ideal.map (algebraMap R (Localization.AtPrime P)) J) : + I ≤ J := by + intro x hx + suffices J.colon (Ideal.span {x}) = ⊤ by + simpa using Submodule.mem_colon.mp + (show (1 : R) ∈ J.colon (Ideal.span {x}) from this.symm ▸ Submodule.mem_top) x + (Ideal.mem_span_singleton_self x) + refine Not.imp_symm (J.colon (Ideal.span {x})).exists_le_maximal ?_ + push_neg + intro P hP le + obtain ⟨⟨⟨a, ha⟩, ⟨s, hs⟩⟩, eq⟩ := + (IsLocalization.mem_map_algebraMap_iff P.primeCompl _).mp (h P hP (Ideal.mem_map_of_mem _ hx)) + rw [← _root_.map_mul, ← sub_eq_zero, ← map_sub] at eq + obtain ⟨⟨m, hm⟩, eq⟩ := (IsLocalization.map_eq_zero_iff P.primeCompl _ _).mp eq + refine hs ((hP.isPrime.mem_or_mem (le (Ideal.mem_colon_singleton.mpr ?_))).resolve_right hm) + simp only [Subtype.coe_mk, mul_sub, sub_eq_zero, mul_comm x s, mul_left_comm] at eq + simpa only [mul_assoc, eq] using J.mul_mem_left m ha + +/-- Let `I J : Ideal R`. If the localization of `I` at each maximal ideal `P` is equal to +the localization of `J` at `P`, then `I = J`. -/ +theorem Ideal.eq_of_localization_maximal {I J : Ideal R} + (h : ∀ (P : Ideal R) (_ : P.IsMaximal), + Ideal.map (algebraMap R (Localization.AtPrime P)) I = + Ideal.map (algebraMap R (Localization.AtPrime P)) J) : + I = J := + le_antisymm (Ideal.le_of_localization_maximal fun P hP => (h P hP).le) + (Ideal.le_of_localization_maximal fun P hP => (h P hP).ge) + +/-- An ideal is trivial if its localization at every maximal ideal is trivial. -/ +theorem ideal_eq_bot_of_localization' (I : Ideal R) + (h : ∀ (J : Ideal R) (hJ : J.IsMaximal), + Ideal.map (algebraMap R (Localization.AtPrime J)) I = ⊥) : + I = ⊥ := + Ideal.eq_of_localization_maximal fun P hP => by simpa using h P hP + +-- TODO: This proof should work for all modules, once we have enough material on submodules of +-- localized modules. +/-- An ideal is trivial if its localization at every maximal ideal is trivial. -/ +theorem ideal_eq_bot_of_localization (I : Ideal R) + (h : ∀ (J : Ideal R) (hJ : J.IsMaximal), + IsLocalization.coeSubmodule (Localization.AtPrime J) I = ⊥) : + I = ⊥ := + ideal_eq_bot_of_localization' _ fun P hP => + (Ideal.map_eq_bot_iff_le_ker _).mpr fun x hx => by + rw [RingHom.mem_ker, ← Submodule.mem_bot R, ← h P hP, IsLocalization.mem_coeSubmodule] + exact ⟨x, hx, rfl⟩ + +theorem eq_zero_of_localization (r : R) + (h : ∀ (J : Ideal R) (hJ : J.IsMaximal), algebraMap R (Localization.AtPrime J) r = 0) : + r = 0 := by + rw [← Ideal.span_singleton_eq_bot] + apply ideal_eq_bot_of_localization + intro J hJ + delta IsLocalization.coeSubmodule + erw [Submodule.map_span, Submodule.span_eq_bot] + rintro _ ⟨_, h', rfl⟩ + cases Set.mem_singleton_iff.mpr h' + exact h J hJ + +end Ideal diff --git a/Mathlib/RingTheory/LocalProperties/IntegrallyClosed.lean b/Mathlib/RingTheory/LocalProperties/IntegrallyClosed.lean new file mode 100644 index 0000000000000..3753f3c70b5be --- /dev/null +++ b/Mathlib/RingTheory/LocalProperties/IntegrallyClosed.lean @@ -0,0 +1,68 @@ +/- +Copyright (c) 2024 Yongle Hu. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yongle Hu +-/ +import Mathlib.RingTheory.IntegralClosure.IntegrallyClosed +import Mathlib.RingTheory.LocalProperties.Basic +import Mathlib.RingTheory.Localization.LocalizationLocalization + +/-! +# `IsIntegrallyClosed` is a local property + +In this file, we prove that `IsIntegrallyClosed` is a local property. + +## Main results + +* `IsIntegrallyClosed.of_localization_maximal` : An integral domain `R` is integral closed + if `Rₘ` is integral closed for any maximal ideal `m` of `R`. + +## TODO + +Prove that `IsIntegrallyClosed` is preserved by localization + +-/ + +open scoped nonZeroDivisors + +open Localization Ideal IsLocalization + +/-- An integral domain `R` is integral closed if `Rₘ` is integral closed + for any maximal ideal `m` of `R`. -/ +theorem IsIntegrallyClosed.of_localization_maximal {R : Type*} [CommRing R] [IsDomain R] + (h : ∀ p : Ideal R, p ≠ ⊥ → [p.IsMaximal] → IsIntegrallyClosed (Localization.AtPrime p)) : + IsIntegrallyClosed R := by + by_cases hf : IsField R + · exact hf.toField.instIsIntegrallyClosed + apply (isIntegrallyClosed_iff (FractionRing R)).mpr + rintro ⟨x⟩ hx + let I : Ideal R := span {x.2.1} / span {x.1} + have h1 : 1 ∈ I := by + apply I.eq_top_iff_one.mp + by_contra hn + rcases I.exists_le_maximal hn with ⟨p, hpm, hpi⟩ + have hic := h p (Ring.ne_bot_of_isMaximal_of_not_isField hpm hf) + have hxp : IsIntegral (Localization.AtPrime p) (mk x.1 x.2) := hx.tower_top + /- `x.1 / x.2.1 ∈ Rₚ` since it is integral over `Rₚ` and `Rₚ` is integrally closed. + More precisely, `x.1 / x.2.1 = y.1 / y.2.1` where `y.1, y.2.1 ∈ R` and `y.2.1 ∉ p`. -/ + rcases (isIntegrallyClosed_iff (FractionRing R)).mp hic hxp with ⟨⟨y⟩, hy⟩ + /- `y.2.1 ∈ I` since for all `a ∈ Ideal.span {x.1}`, say `a = b * x.1`, + we have `y.2 * a = b * x.1 * y.2 = b * y.1 * x.2.1 ∈ Ideal.span {x.2.1}`. -/ + have hyi : y.2.1 ∈ I := by + intro a ha + rcases mem_span_singleton'.mp ha with ⟨b, hb⟩ + apply mem_span_singleton'.mpr ⟨b * y.1, _⟩ + rw [← hb, ← mul_assoc, mul_comm y.2.1 b, mul_assoc, mul_assoc] + exact congrArg (HMul.hMul b) <| (mul_comm y.1 x.2.1).trans <| + NoZeroSMulDivisors.algebraMap_injective R (Localization R⁰) <| mk'_eq_iff_eq.mp <| + (mk'_eq_algebraMap_mk'_of_submonoid_le _ _ p.primeCompl_le_nonZeroDivisors y.1 y.2).trans + <| show algebraMap (Localization.AtPrime p) _ (mk' _ y.1 y.2) = mk' _ x.1 x.2 + by simpa only [← mk_eq_mk', ← hy] using by rfl + -- `y.2.1 ∈ I` implies `y.2.1 ∈ p` since `I ⊆ p`, which contradicts to the choice of `y`. + exact y.2.2 (hpi hyi) + rcases mem_span_singleton'.mp (h1 x.1 (mem_span_singleton_self x.1)) with ⟨y, hy⟩ + exact ⟨y, (eq_mk'_of_mul_eq (hy.trans (one_mul x.1))).trans (mk_eq_mk'_apply x.1 x.2).symm⟩ + +theorem isIntegrallyClosed_ofLocalizationMaximal : + OfLocalizationMaximal fun R _ => ([IsDomain R] → IsIntegrallyClosed R) := + fun _ _ h _ ↦ IsIntegrallyClosed.of_localization_maximal fun p _ hpm ↦ h p hpm diff --git a/Mathlib/RingTheory/LocalProperties/Reduced.lean b/Mathlib/RingTheory/LocalProperties/Reduced.lean new file mode 100644 index 0000000000000..65df178848887 --- /dev/null +++ b/Mathlib/RingTheory/LocalProperties/Reduced.lean @@ -0,0 +1,53 @@ +/- +Copyright (c) 2021 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.LocalProperties.Basic + +/-! +# `IsReduced` is a local property + +In this file, we prove that `IsReduced` is a local property. + +## Main results + +Let `R` be a commutative ring, `M` be a submonoid of `R`. + +* `isReduced_localizationPreserves` : `M⁻¹R` is reduced if `R` is reduced. +* `isReduced_ofLocalizationMaximal` : `R` is reduced if `Rₘ` is reduced for all maximal ideal `m`. + +-/ + +/-- `M⁻¹R` is reduced if `R` is reduced. -/ +theorem isReduced_localizationPreserves : LocalizationPreserves fun R hR => IsReduced R := by + introv R _ _ + constructor + rintro x ⟨_ | n, e⟩ + · simpa using congr_arg (· * x) e + obtain ⟨⟨y, m⟩, hx⟩ := IsLocalization.surj M x + dsimp only at hx + let hx' := congr_arg (· ^ n.succ) hx + simp only [mul_pow, e, zero_mul, ← RingHom.map_pow] at hx' + rw [← (algebraMap R S).map_zero] at hx' + obtain ⟨m', hm'⟩ := (IsLocalization.eq_iff_exists M S).mp hx' + apply_fun (· * (m' : R) ^ n) at hm' + simp only [mul_assoc, zero_mul, mul_zero] at hm' + rw [← mul_left_comm, ← pow_succ', ← mul_pow] at hm' + replace hm' := IsNilpotent.eq_zero ⟨_, hm'.symm⟩ + rw [← (IsLocalization.map_units S m).mul_left_inj, hx, zero_mul, + IsLocalization.map_eq_zero_iff M] + exact ⟨m', by rw [← hm', mul_comm]⟩ + +instance {R : Type*} [CommRing R] (M : Submonoid R) [IsReduced R] : IsReduced (Localization M) := + isReduced_localizationPreserves M _ inferInstance + +/-- `R` is reduced if `Rₘ` is reduced for all maximal ideal `m`. -/ +theorem isReduced_ofLocalizationMaximal : OfLocalizationMaximal fun R hR => IsReduced R := by + introv R h + constructor + intro x hx + apply eq_zero_of_localization + intro J hJ + specialize h J hJ + exact (hx.map <| algebraMap R <| Localization.AtPrime J).eq_zero diff --git a/Mathlib/RingTheory/Localization/Finiteness.lean b/Mathlib/RingTheory/Localization/Finiteness.lean index e14b622040c88..ab340bfec9330 100644 --- a/Mathlib/RingTheory/Localization/Finiteness.lean +++ b/Mathlib/RingTheory/Localization/Finiteness.lean @@ -5,7 +5,7 @@ Authors: Christian Merten -/ import Mathlib.Algebra.Module.LocalizedModuleIntegers import Mathlib.RingTheory.Localization.Algebra -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.RingHom.Finite /-! diff --git a/Mathlib/RingTheory/RingHom/Finite.lean b/Mathlib/RingTheory/RingHom/Finite.lean index 164f6abef7265..40a5dbe72b097 100644 --- a/Mathlib/RingTheory/RingHom/Finite.lean +++ b/Mathlib/RingTheory/RingHom/Finite.lean @@ -3,12 +3,22 @@ Copyright (c) 2021 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.RingTheory.RingHomProperties +import Mathlib.RingTheory.LocalProperties.Basic +import Mathlib.RingTheory.Localization.Integer /-! # The meta properties of finite ring homomorphisms. +## Main results + +Let `R` be a commutative ring, `S` is an `R`-algebra, `M` be a submonoid of `R`. + +* `finite_localizationPreserves` : If `S` is a finite `R`-algebra, then `S' = M⁻¹S` is a + finite `R' = M⁻¹R`-algebra. +* `finite_ofLocalizationSpan` : `S` is a finite `R`-algebra if there exists + a set `{ r }` that spans `R` such that `Sᵣ` is a finite `Rᵣ`-algebra. + -/ @@ -38,3 +48,186 @@ theorem finite_stableUnderBaseChange : StableUnderBaseChange @Finite := by exact inferInstance end RingHom + +open scoped Pointwise Classical + +universe u + +variable {R S : Type u} [CommRing R] [CommRing S] (M : Submonoid R) (f : R →+* S) +variable (R' S' : Type u) [CommRing R'] [CommRing S'] +variable [Algebra R R'] [Algebra S S'] + +lemma Module.Finite_of_isLocalization (R S Rₚ Sₚ) [CommSemiring R] [CommRing S] [CommRing Rₚ] + [CommRing Sₚ] [Algebra R S] [Algebra R Rₚ] [Algebra R Sₚ] [Algebra S Sₚ] [Algebra Rₚ Sₚ] + [IsScalarTower R S Sₚ] [IsScalarTower R Rₚ Sₚ] (M : Submonoid R) [IsLocalization M Rₚ] + [IsLocalization (Algebra.algebraMapSubmonoid S M) Sₚ] [hRS : Module.Finite R S] : + Module.Finite Rₚ Sₚ := by + classical + have : algebraMap Rₚ Sₚ = IsLocalization.map (T := Algebra.algebraMapSubmonoid S M) Sₚ + (algebraMap R S) (Submonoid.le_comap_map M) := by + apply IsLocalization.ringHom_ext M + simp only [IsLocalization.map_comp, ← IsScalarTower.algebraMap_eq] + -- We claim that if `S` is generated by `T` as an `R`-module, + -- then `S'` is generated by `T` as an `R'`-module. + obtain ⟨T, hT⟩ := hRS + use T.image (algebraMap S Sₚ) + rw [eq_top_iff] + rintro x - + -- By the hypotheses, for each `x : S'`, we have `x = y / (f r)` for some `y : S` and `r : M`. + -- Since `S` is generated by `T`, the image of `y` should fall in the span of the image of `T`. + obtain ⟨y, ⟨_, ⟨r, hr, rfl⟩⟩, rfl⟩ := + IsLocalization.mk'_surjective (Algebra.algebraMapSubmonoid S M) x + rw [IsLocalization.mk'_eq_mul_mk'_one, mul_comm, Finset.coe_image] + have hy : y ∈ Submodule.span R ↑T := by rw [hT]; trivial + replace hy : algebraMap S Sₚ y ∈ Submodule.map (IsScalarTower.toAlgHom R S Sₚ).toLinearMap + (Submodule.span R (T : Set S)) := Submodule.mem_map_of_mem +-- -- Note: #8386 had to specify the value of `f` below + (f := (IsScalarTower.toAlgHom R S Sₚ).toLinearMap) hy + rw [Submodule.map_span (IsScalarTower.toAlgHom R S Sₚ).toLinearMap T] at hy + have H : Submodule.span R (algebraMap S Sₚ '' T) ≤ + (Submodule.span Rₚ (algebraMap S Sₚ '' T)).restrictScalars R := by + rw [Submodule.span_le]; exact Submodule.subset_span + -- Now, since `y ∈ span T`, and `(f r)⁻¹ ∈ R'`, `x / (f r)` is in `span T` as well. + convert (Submodule.span Rₚ (algebraMap S Sₚ '' T)).smul_mem + (IsLocalization.mk' Rₚ (1 : R) ⟨r, hr⟩) (H hy) using 1 + rw [Algebra.smul_def, this, IsLocalization.map_mk', map_one] + +/-- If `S` is a finite `R`-algebra, then `S' = M⁻¹S` is a finite `R' = M⁻¹R`-algebra. -/ +theorem RingHom.finite_localizationPreserves : RingHom.LocalizationPreserves @RingHom.Finite := by + introv R hf + letI := f.toAlgebra + letI := ((algebraMap S S').comp f).toAlgebra + let f' : R' →+* S' := IsLocalization.map S' f (Submonoid.le_comap_map M) + letI := f'.toAlgebra + have : IsScalarTower R R' S' := IsScalarTower.of_algebraMap_eq' + (IsLocalization.map_comp M.le_comap_map).symm + have : IsScalarTower R S S' := IsScalarTower.of_algebraMap_eq' rfl + have : IsLocalization (Algebra.algebraMapSubmonoid S M) S' := by + rwa [Algebra.algebraMapSubmonoid, RingHom.algebraMap_toAlgebra] + have : Module.Finite R S := hf + apply Module.Finite_of_isLocalization R S R' S' M + +theorem RingHom.localization_away_map_finite (r : R) [IsLocalization.Away r R'] + [IsLocalization.Away (f r) S'] (hf : f.Finite) : (IsLocalization.Away.map R' S' f r).Finite := + finite_localizationPreserves.away r hf + +/-- Let `S` be an `R`-algebra, `M` a submonoid of `R`, and `S' = M⁻¹S`. +If the image of some `x : S` falls in the span of some finite `s ⊆ S'` over `R`, +then there exists some `m : M` such that `m • x` falls in the +span of `IsLocalization.finsetIntegerMultiple _ s` over `R`. +-/ +theorem IsLocalization.smul_mem_finsetIntegerMultiple_span [Algebra R S] [Algebra R S'] + [IsScalarTower R S S'] [IsLocalization (M.map (algebraMap R S)) S'] (x : S) (s : Finset S') + (hx : algebraMap S S' x ∈ Submodule.span R (s : Set S')) : + ∃ m : M, m • x ∈ + Submodule.span R + (IsLocalization.finsetIntegerMultiple (M.map (algebraMap R S)) s : Set S) := by + let g : S →ₐ[R] S' := + AlgHom.mk' (algebraMap S S') fun c x => by simp [Algebra.algebraMap_eq_smul_one] + -- We first obtain the `y' ∈ M` such that `s' = y' • s` is falls in the image of `S` in `S'`. + let y := IsLocalization.commonDenomOfFinset (M.map (algebraMap R S)) s + have hx₁ : (y : S) • (s : Set S') = g '' _ := + (IsLocalization.finsetIntegerMultiple_image _ s).symm + obtain ⟨y', hy', e : algebraMap R S y' = y⟩ := y.prop + have : algebraMap R S y' • (s : Set S') = y' • (s : Set S') := by + simp_rw [Algebra.algebraMap_eq_smul_one, smul_assoc, one_smul] + rw [← e, this] at hx₁ + replace hx₁ := congr_arg (Submodule.span R) hx₁ + rw [Submodule.span_smul] at hx₁ + replace hx : _ ∈ y' • Submodule.span R (s : Set S') := Set.smul_mem_smul_set hx + rw [hx₁] at hx + erw [← _root_.map_smul g, ← Submodule.map_span (g : S →ₗ[R] S')] at hx + -- Since `x` falls in the span of `s` in `S'`, `y' • x : S` falls in the span of `s'` in `S'`. + -- That is, there exists some `x' : S` in the span of `s'` in `S` and `x' = y' • x` in `S'`. + -- Thus `a • (y' • x) = a • x' ∈ span s'` in `S` for some `a ∈ M`. + obtain ⟨x', hx', hx'' : algebraMap _ _ _ = _⟩ := hx + obtain ⟨⟨_, a, ha₁, rfl⟩, ha₂⟩ := + (IsLocalization.eq_iff_exists (M.map (algebraMap R S)) S').mp hx'' + use (⟨a, ha₁⟩ : M) * (⟨y', hy'⟩ : M) + convert (Submodule.span R + (IsLocalization.finsetIntegerMultiple (Submonoid.map (algebraMap R S) M) s : Set S)).smul_mem + a hx' using 1 + convert ha₂.symm using 1 + · rw [Subtype.coe_mk, Submonoid.smul_def, Submonoid.coe_mul, ← smul_smul] + exact Algebra.smul_def _ _ + · exact Algebra.smul_def _ _ + +/-- If `M` is an `R' = S⁻¹R` module, and `x ∈ span R' s`, +then `t • x ∈ span R s` for some `t : S`. -/ +theorem multiple_mem_span_of_mem_localization_span + {N : Type*} [AddCommMonoid N] [Module R N] [Module R' N] + [IsScalarTower R R' N] [IsLocalization M R'] (s : Set N) (x : N) + (hx : x ∈ Submodule.span R' s) : ∃ (t : M), t • x ∈ Submodule.span R s := by + classical + obtain ⟨s', hss', hs'⟩ := Submodule.mem_span_finite_of_mem_span hx + rsuffices ⟨t, ht⟩ : ∃ t : M, t • x ∈ Submodule.span R (s' : Set N) + · exact ⟨t, Submodule.span_mono hss' ht⟩ + clear hx hss' s + induction s' using Finset.induction_on generalizing x + · use 1; simpa using hs' + rename_i a s _ hs + simp only [Finset.coe_insert, Finset.image_insert, Finset.coe_image, Subtype.coe_mk, + Submodule.mem_span_insert] at hs' ⊢ + rcases hs' with ⟨y, z, hz, rfl⟩ + rcases IsLocalization.surj M y with ⟨⟨y', s'⟩, e⟩ + apply congrArg (fun x ↦ x • a) at e + simp only [algebraMap_smul] at e + rcases hs _ hz with ⟨t, ht⟩ + refine ⟨t * s', t * y', _, (Submodule.span R (s : Set N)).smul_mem s' ht, ?_⟩ + rw [smul_add, ← smul_smul, mul_comm, ← smul_smul, ← smul_smul, ← e, mul_comm, ← Algebra.smul_def] + simp + rfl + +/-- If `S` is an `R' = M⁻¹R` algebra, and `x ∈ adjoin R' s`, +then `t • x ∈ adjoin R s` for some `t : M`. -/ +theorem multiple_mem_adjoin_of_mem_localization_adjoin [Algebra R' S] [Algebra R S] + [IsScalarTower R R' S] [IsLocalization M R'] (s : Set S) (x : S) + (hx : x ∈ Algebra.adjoin R' s) : ∃ t : M, t • x ∈ Algebra.adjoin R s := by + change ∃ t : M, t • x ∈ Subalgebra.toSubmodule (Algebra.adjoin R s) + change x ∈ Subalgebra.toSubmodule (Algebra.adjoin R' s) at hx + simp_rw [Algebra.adjoin_eq_span] at hx ⊢ + exact multiple_mem_span_of_mem_localization_span M R' _ _ hx + +/-- `S` is a finite `R`-algebra if there exists a set `{ r }` that + spans `R` such that `Sᵣ` is a finite `Rᵣ`-algebra. -/ +theorem RingHom.finite_ofLocalizationSpan : RingHom.OfLocalizationSpan @RingHom.Finite := by + rw [RingHom.ofLocalizationSpan_iff_finite] + introv R hs H + -- We first setup the instances + letI := f.toAlgebra + letI := fun r : s => (Localization.awayMap f r).toAlgebra + have : ∀ r : s, + IsLocalization ((Submonoid.powers (r : R)).map (algebraMap R S)) (Localization.Away (f r)) := + by intro r; rw [Submonoid.map_powers]; exact Localization.isLocalization + haveI : ∀ r : s, IsScalarTower R (Localization.Away (r : R)) (Localization.Away (f r)) := + fun r => IsScalarTower.of_algebraMap_eq' + (IsLocalization.map_comp (Submonoid.powers (r : R)).le_comap_map).symm + -- By the hypothesis, we may find a finite generating set for each `Sᵣ`. This set can then be + -- lifted into `R` by multiplying a sufficiently large power of `r`. I claim that the union of + -- these generates `S`. + constructor + replace H := fun r => (H r).1 + choose s₁ s₂ using H + let sf := fun x : s => IsLocalization.finsetIntegerMultiple (Submonoid.powers (f x)) (s₁ x) + use s.attach.biUnion sf + rw [Submodule.span_attach_biUnion, eq_top_iff] + -- It suffices to show that `r ^ n • x ∈ span T` for each `r : s`, since `{ r ^ n }` spans `R`. + -- This then follows from the fact that each `x : R` is a linear combination of the generating set + -- of `Sᵣ`. By multiplying a sufficiently large power of `r`, we can cancel out the `r`s in the + -- denominators of both the generating set and the coefficients. + rintro x - + apply Submodule.mem_of_span_eq_top_of_smul_pow_mem _ (s : Set R) hs _ _ + intro r + obtain ⟨⟨_, n₁, rfl⟩, hn₁⟩ := + multiple_mem_span_of_mem_localization_span (Submonoid.powers (r : R)) + (Localization.Away (r : R)) (s₁ r : Set (Localization.Away (f r))) (algebraMap S _ x) + (by rw [s₂ r]; trivial) + dsimp only at hn₁ + rw [Submonoid.smul_def, Algebra.smul_def, IsScalarTower.algebraMap_apply R S, ← map_mul] at hn₁ + obtain ⟨⟨_, n₂, rfl⟩, hn₂⟩ := + IsLocalization.smul_mem_finsetIntegerMultiple_span (Submonoid.powers (r : R)) + (Localization.Away (f r)) _ (s₁ r) hn₁ + rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, ← pow_add] at hn₂ + simp_rw [Submonoid.map_powers] at hn₂ + use n₂ + n₁ + exact le_iSup (fun x : s => Submodule.span R (sf x : Set S)) r hn₂ diff --git a/Mathlib/RingTheory/RingHom/FiniteType.lean b/Mathlib/RingTheory/RingHom/FiniteType.lean index 3f927873decf1..1e07b805c0c4a 100644 --- a/Mathlib/RingTheory/RingHom/FiniteType.lean +++ b/Mathlib/RingTheory/RingHom/FiniteType.lean @@ -4,26 +4,154 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.RingTheory.FiniteStability -import Mathlib.RingTheory.LocalProperties import Mathlib.RingTheory.Localization.InvSubmonoid +import Mathlib.RingTheory.RingHom.Finite /-! # The meta properties of finite-type ring homomorphisms. -The main result is `RingHom.finiteType_is_local`. +## Main results + +Let `R` be a commutative ring, `S` is an `R`-algebra, `M` be a submonoid of `R`. + +* `finiteType_localizationPreserves` : If `S` is a finite type `R`-algebra, then `S' = M⁻¹S` is a + finite type `R' = M⁻¹R`-algebra. +* `finiteType_ofLocalizationSpan` : `S` is a finite type `R`-algebra if there exists + a set `{ r }` that spans `R` such that `Sᵣ` is a finite type `Rᵣ`-algebra. +*`RingHom.finiteType_is_local`: `RingHom.FiniteType` is a local property. -/ namespace RingHom -open scoped Pointwise TensorProduct +open scoped Pointwise TensorProduct Classical + +universe u + +variable {R S : Type u} [CommRing R] [CommRing S] (M : Submonoid R) (f : R →+* S) +variable (R' S' : Type u) [CommRing R'] [CommRing S'] +variable [Algebra R R'] [Algebra S S'] theorem finiteType_stableUnderComposition : StableUnderComposition @FiniteType := by introv R hf hg exact hg.comp hf +/-- If `S` is a finite type `R`-algebra, then `S' = M⁻¹S` is a finite type `R' = M⁻¹R`-algebra. -/ +theorem finiteType_localizationPreserves : RingHom.LocalizationPreserves @RingHom.FiniteType := by + introv R hf + -- mirrors the proof of `localization_map_finite` + letI := f.toAlgebra + letI := ((algebraMap S S').comp f).toAlgebra + let f' : R' →+* S' := IsLocalization.map S' f (Submonoid.le_comap_map M) + letI := f'.toAlgebra + haveI : IsScalarTower R R' S' := + IsScalarTower.of_algebraMap_eq' (IsLocalization.map_comp M.le_comap_map).symm + let fₐ : S →ₐ[R] S' := AlgHom.mk' (algebraMap S S') fun c x => RingHom.map_mul _ _ _ + obtain ⟨T, hT⟩ := hf + use T.image (algebraMap S S') + rw [eq_top_iff] + rintro x - + obtain ⟨y, ⟨_, ⟨r, hr, rfl⟩⟩, rfl⟩ := IsLocalization.mk'_surjective (M.map f) x + rw [IsLocalization.mk'_eq_mul_mk'_one, mul_comm, Finset.coe_image] + have hy : y ∈ Algebra.adjoin R (T : Set S) := by rw [hT]; trivial + replace hy : algebraMap S S' y ∈ (Algebra.adjoin R (T : Set S)).map fₐ := + Subalgebra.mem_map.mpr ⟨_, hy, rfl⟩ + rw [fₐ.map_adjoin T] at hy + have H : Algebra.adjoin R (algebraMap S S' '' T) ≤ + (Algebra.adjoin R' (algebraMap S S' '' T)).restrictScalars R := by + rw [Algebra.adjoin_le_iff]; exact Algebra.subset_adjoin + convert (Algebra.adjoin R' (algebraMap S S' '' T)).smul_mem (H hy) + (IsLocalization.mk' R' (1 : R) ⟨r, hr⟩) using 1 + rw [Algebra.smul_def] + erw [IsLocalization.map_mk' M.le_comap_map] + rw [map_one] + +theorem localization_away_map_finiteType (r : R) [IsLocalization.Away r R'] + [IsLocalization.Away (f r) S'] (hf : f.FiniteType) : + (IsLocalization.Away.map R' S' f r).FiniteType := + finiteType_localizationPreserves.away r hf + +variable {S'} + +/-- Let `S` be an `R`-algebra, `M` a submonoid of `S`, `S' = M⁻¹S`. +Suppose the image of some `x : S` falls in the adjoin of some finite `s ⊆ S'` over `R`, +and `A` is an `R`-subalgebra of `S` containing both `M` and the numerators of `s`. +Then, there exists some `m : M` such that `m • x` falls in `A`. +-/ +theorem IsLocalization.exists_smul_mem_of_mem_adjoin [Algebra R S] [Algebra R S'] + [IsScalarTower R S S'] (M : Submonoid S) [IsLocalization M S'] (x : S) (s : Finset S') + (A : Subalgebra R S) (hA₁ : (IsLocalization.finsetIntegerMultiple M s : Set S) ⊆ A) + (hA₂ : M ≤ A.toSubmonoid) (hx : algebraMap S S' x ∈ Algebra.adjoin R (s : Set S')) : + ∃ m : M, m • x ∈ A := by + let g : S →ₐ[R] S' := IsScalarTower.toAlgHom R S S' + let y := IsLocalization.commonDenomOfFinset M s + have hx₁ : (y : S) • (s : Set S') = g '' _ := + (IsLocalization.finsetIntegerMultiple_image _ s).symm + obtain ⟨n, hn⟩ := + Algebra.pow_smul_mem_of_smul_subset_of_mem_adjoin (y : S) (s : Set S') (A.map g) + (by rw [hx₁]; exact Set.image_subset _ hA₁) hx (Set.mem_image_of_mem _ (hA₂ y.2)) + obtain ⟨x', hx', hx''⟩ := hn n (le_of_eq rfl) + rw [Algebra.smul_def, ← _root_.map_mul] at hx'' + obtain ⟨a, ha₂⟩ := (IsLocalization.eq_iff_exists M S').mp hx'' + use a * y ^ n + convert A.mul_mem hx' (hA₂ a.prop) using 1 + rw [Submonoid.smul_def, smul_eq_mul, Submonoid.coe_mul, SubmonoidClass.coe_pow, mul_assoc, ← ha₂, + mul_comm] + +/-- Let `S` be an `R`-algebra, `M` a submonoid of `R`, and `S' = M⁻¹S`. +If the image of some `x : S` falls in the adjoin of some finite `s ⊆ S'` over `R`, +then there exists some `m : M` such that `m • x` falls in the +adjoin of `IsLocalization.finsetIntegerMultiple _ s` over `R`. +-/ +theorem IsLocalization.lift_mem_adjoin_finsetIntegerMultiple [Algebra R S] [Algebra R S'] + [IsScalarTower R S S'] [IsLocalization (M.map (algebraMap R S)) S'] (x : S) (s : Finset S') + (hx : algebraMap S S' x ∈ Algebra.adjoin R (s : Set S')) : + ∃ m : M, m • x ∈ + Algebra.adjoin R + (IsLocalization.finsetIntegerMultiple (M.map (algebraMap R S)) s : Set S) := by + obtain ⟨⟨_, a, ha, rfl⟩, e⟩ := + IsLocalization.exists_smul_mem_of_mem_adjoin (M.map (algebraMap R S)) x s (Algebra.adjoin R _) + Algebra.subset_adjoin (by rintro _ ⟨a, _, rfl⟩; exact Subalgebra.algebraMap_mem _ a) hx + refine ⟨⟨a, ha⟩, ?_⟩ + simpa only [Submonoid.smul_def, algebraMap_smul] using e + +theorem finiteType_ofLocalizationSpan : RingHom.OfLocalizationSpan @RingHom.FiniteType := by + rw [RingHom.ofLocalizationSpan_iff_finite] + introv R hs H + -- mirrors the proof of `finite_ofLocalizationSpan` + letI := f.toAlgebra + letI := fun r : s => (Localization.awayMap f r).toAlgebra + have : ∀ r : s, + IsLocalization ((Submonoid.powers (r : R)).map (algebraMap R S)) (Localization.Away (f r)) := + by intro r; rw [Submonoid.map_powers]; exact Localization.isLocalization + haveI : ∀ r : s, IsScalarTower R (Localization.Away (r : R)) (Localization.Away (f r)) := + fun r => IsScalarTower.of_algebraMap_eq' + (IsLocalization.map_comp (Submonoid.powers (r : R)).le_comap_map).symm + constructor + replace H := fun r => (H r).1 + choose s₁ s₂ using H + let sf := fun x : s => IsLocalization.finsetIntegerMultiple (Submonoid.powers (f x)) (s₁ x) + use s.attach.biUnion sf + convert (Algebra.adjoin_attach_biUnion (R := R) sf).trans _ + rw [eq_top_iff] + rintro x - + apply (⨆ x : s, Algebra.adjoin R (sf x : Set S)).toSubmodule.mem_of_span_eq_top_of_smul_pow_mem + _ hs _ _ + intro r + obtain ⟨⟨_, n₁, rfl⟩, hn₁⟩ := + multiple_mem_adjoin_of_mem_localization_adjoin (Submonoid.powers (r : R)) + (Localization.Away (r : R)) (s₁ r : Set (Localization.Away (f r))) + (algebraMap S (Localization.Away (f r)) x) (by rw [s₂ r]; trivial) + rw [Submonoid.smul_def, Algebra.smul_def, IsScalarTower.algebraMap_apply R S, ← map_mul] at hn₁ + obtain ⟨⟨_, n₂, rfl⟩, hn₂⟩ := + IsLocalization.lift_mem_adjoin_finsetIntegerMultiple (Submonoid.powers (r : R)) _ (s₁ r) hn₁ + rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, ← pow_add] at hn₂ + simp_rw [Submonoid.map_powers] at hn₂ + use n₂ + n₁ + exact le_iSup (fun x : s => Algebra.adjoin R (sf x : Set S)) r hn₂ + theorem finiteType_holdsForLocalizationAway : HoldsForLocalizationAway @FiniteType := by introv R _ suffices Algebra.FiniteType R S by @@ -88,7 +216,7 @@ theorem finiteType_ofLocalizationSpanTarget : OfLocalizationSpanTarget @FiniteTy · rw [ht]; trivial theorem finiteType_is_local : PropertyIsLocal @FiniteType := - ⟨localization_finiteType, finiteType_ofLocalizationSpanTarget, + ⟨finiteType_localizationPreserves, finiteType_ofLocalizationSpanTarget, finiteType_stableUnderComposition.stableUnderCompositionWithLocalizationAway finiteType_holdsForLocalizationAway⟩ diff --git a/Mathlib/RingTheory/RingHom/Surjective.lean b/Mathlib/RingTheory/RingHom/Surjective.lean index 11bc6f10f5271..b20eeffe62179 100644 --- a/Mathlib/RingTheory/RingHom/Surjective.lean +++ b/Mathlib/RingTheory/RingHom/Surjective.lean @@ -3,12 +3,22 @@ Copyright (c) 2022 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.LocalProperties.Basic /-! # The meta properties of surjective ring homomorphisms. +## Main results + +Let `R` be a commutative ring, `M` be a submonoid of `R`. + +* `surjective_localizationPreserves` : `M⁻¹R →+* M⁻¹S` is surjective if `R →+* S` is surjective. +* `surjective_ofLocalizationSpan` : `R →+* S` is surjective if there exists a set `{ r }` that + spans `R` such that `Rᵣ →+* Sᵣ` is surjective. +* `surjective_localRingHom_of_surjective` : A surjective ring homomorphism `R →+* S` induces a + surjective homomorphism `R_{f⁻¹(P)} →+* S_P` for every prime ideal `P` of `S`. + -/ @@ -18,6 +28,8 @@ open scoped TensorProduct open TensorProduct Algebra.TensorProduct +universe u + local notation "surjective" => fun {X Y : Type _} [CommRing X] [CommRing Y] => fun f : X →+* Y => Function.Surjective f @@ -40,28 +52,41 @@ theorem surjective_stableUnderBaseChange : StableUnderBaseChange surjective := b rw [TensorProduct.smul_tmul, Algebra.algebraMap_eq_smul_one] | add x y ex ey => obtain ⟨⟨x, rfl⟩, ⟨y, rfl⟩⟩ := ex, ey; exact ⟨x + y, map_add _ x y⟩ +/-- `M⁻¹R →+* M⁻¹S` is surjective if `R →+* S` is surjective. -/ +theorem surjective_localizationPreserves : + LocalizationPreserves surjective := by + introv R H x + obtain ⟨x, ⟨_, s, hs, rfl⟩, rfl⟩ := IsLocalization.mk'_surjective (M.map f) x + obtain ⟨y, rfl⟩ := H x + use IsLocalization.mk' R' y ⟨s, hs⟩ + rw [IsLocalization.map_mk'] + +/-- `R →+* S` is surjective if there exists a set `{ r }` that spans `R` such that + `Rᵣ →+* Sᵣ` is surjective. -/ theorem surjective_ofLocalizationSpan : OfLocalizationSpan surjective := by - introv R hs H + introv R e H + rw [← Set.range_iff_surjective, Set.eq_univ_iff_forall] letI := f.toAlgebra - show Function.Surjective (Algebra.ofId R S) - rw [← Algebra.range_top_iff_surjective, eq_top_iff] - rintro x - - obtain ⟨l, hl⟩ := - (Finsupp.mem_span_iff_linearCombination R s 1).mp (show _ ∈ Ideal.span s by rw [hs]; trivial) - fapply - Subalgebra.mem_of_finset_sum_eq_one_of_pow_smul_mem _ l.support (fun x : s => f x) fun x : s => - f (l x) - · simp_rw [← _root_.map_mul, ← map_sum, ← f.map_one]; exact f.congr_arg hl - · exact fun _ => Set.mem_range_self _ - · exact fun _ => Set.mem_range_self _ - · intro r - obtain ⟨y, hy⟩ := H r (IsLocalization.mk' _ x (1 : Submonoid.powers (f r))) - obtain ⟨z, ⟨_, n, rfl⟩, rfl⟩ := IsLocalization.mk'_surjective (Submonoid.powers (r : R)) y - erw [IsLocalization.map_mk', IsLocalization.eq] at hy - obtain ⟨⟨_, m, rfl⟩, hm⟩ := hy - refine ⟨m + n, ?_⟩ - dsimp at hm ⊢ - simp_rw [_root_.one_mul, ← _root_.mul_assoc, ← map_pow, ← f.map_mul, ← pow_add, map_pow] at hm - exact ⟨_, hm⟩ + intro x + apply Submodule.mem_of_span_eq_top_of_smul_pow_mem + (LinearMap.range (Algebra.linearMap R S)) s e + intro r + obtain ⟨a, e'⟩ := H r (algebraMap _ _ x) + obtain ⟨b, ⟨_, n, rfl⟩, rfl⟩ := IsLocalization.mk'_surjective (Submonoid.powers (r : R)) a + erw [IsLocalization.map_mk'] at e' + rw [eq_comm, IsLocalization.eq_mk'_iff_mul_eq, Subtype.coe_mk, Subtype.coe_mk, ← map_mul] at e' + obtain ⟨⟨_, n', rfl⟩, e''⟩ := (IsLocalization.eq_iff_exists (Submonoid.powers (f r)) _).mp e' + dsimp only at e'' + rw [mul_comm x, ← mul_assoc, ← map_pow, ← map_mul, ← map_mul, ← pow_add] at e'' + exact ⟨n' + n, _, e''.symm⟩ + +/-- A surjective ring homomorphism `R →+* S` induces a surjective homomorphism `R_{f⁻¹(P)} →+* S_P` +for every prime ideal `P` of `S`. -/ +theorem surjective_localRingHom_of_surjective {R S : Type u} [CommRing R] [CommRing S] + (f : R →+* S) (h : Function.Surjective f) (P : Ideal S) [P.IsPrime] : + Function.Surjective (Localization.localRingHom (P.comap f) P f rfl) := + have : IsLocalization (Submonoid.map f (Ideal.comap f P).primeCompl) (Localization.AtPrime P) := + (Submonoid.map_comap_eq_of_surjective h P.primeCompl).symm ▸ Localization.isLocalization + surjective_localizationPreserves _ _ _ _ h end RingHom From 067644f08fc1c30e218a052be57a7eb3afd546a0 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:00:39 +0000 Subject: [PATCH 132/170] chore: rename Function.comp.assoc to Function.comp_assoc (#17098) --- Mathlib/Algebra/Category/ModuleCat/Free.lean | 2 +- Mathlib/Algebra/Module/PID.lean | 2 +- Mathlib/Algebra/Order/Rearrangement.lean | 4 ++-- Mathlib/AlgebraicGeometry/AffineScheme.lean | 2 +- Mathlib/Analysis/Calculus/ContDiff/Bounds.lean | 2 +- Mathlib/Analysis/Calculus/FDeriv/Equiv.lean | 8 ++++---- Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean | 4 ++-- Mathlib/Analysis/Convex/Intrinsic.lean | 12 ++++++------ Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean | 2 +- Mathlib/Combinatorics/HalesJewett.lean | 2 +- Mathlib/Data/Fin/Tuple/Sort.lean | 2 +- Mathlib/Dynamics/Ergodic/MeasurePreserving.lean | 4 ++-- .../Geometry/Manifold/LocalInvariantProperties.lean | 8 ++++---- Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean | 2 +- .../Geometry/Manifold/SmoothManifoldWithCorners.lean | 2 +- Mathlib/LinearAlgebra/Alternating/Basic.lean | 4 ++-- Mathlib/LinearAlgebra/Determinant.lean | 2 +- Mathlib/LinearAlgebra/LinearDisjoint.lean | 4 ++-- Mathlib/LinearAlgebra/Matrix/Block.lean | 2 +- Mathlib/LinearAlgebra/RootSystem/Hom.lean | 4 ++-- Mathlib/Logic/Function/Basic.lean | 4 ++-- Mathlib/Logic/Function/Defs.lean | 3 ++- Mathlib/MeasureTheory/Function/Jacobian.lean | 2 +- Mathlib/ModelTheory/Basic.lean | 12 ++++++------ Mathlib/ModelTheory/DirectLimit.lean | 4 ++-- Mathlib/ModelTheory/ElementaryMaps.lean | 10 +++++----- Mathlib/ModelTheory/Syntax.lean | 2 +- Mathlib/Topology/Algebra/InfiniteSum/Basic.lean | 2 +- Mathlib/Topology/Category/CompHaus/Projective.lean | 2 +- Mathlib/Topology/Category/Profinite/Nobeling.lean | 4 ++-- Mathlib/Topology/Category/Profinite/Projective.lean | 2 +- Mathlib/Topology/Category/TopCat/EffectiveEpi.lean | 2 +- Mathlib/Topology/ExtremallyDisconnected.lean | 4 ++-- Mathlib/Topology/Homeomorph.lean | 4 ++-- 34 files changed, 66 insertions(+), 65 deletions(-) diff --git a/Mathlib/Algebra/Category/ModuleCat/Free.lean b/Mathlib/Algebra/Category/ModuleCat/Free.lean index ce028e860756f..0cf3303dd9713 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Free.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Free.lean @@ -144,7 +144,7 @@ theorem span_rightExact {w : ι' → S.X₃} (hv : ⊤ ≤ span R (range v)) · convert hw simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, Sum.elim_comp_inr] rw [ModuleCat.epi_iff_surjective] at hE - rw [← Function.comp.assoc, Function.RightInverse.comp_eq_id (Function.rightInverse_invFun hE), + rw [← Function.comp_assoc, Function.RightInverse.comp_eq_id (Function.rightInverse_invFun hE), Function.id_comp] end Span diff --git a/Mathlib/Algebra/Module/PID.lean b/Mathlib/Algebra/Module/PID.lean index 65924b9cdde6d..a00bd3ef0ee93 100644 --- a/Mathlib/Algebra/Module/PID.lean +++ b/Mathlib/Algebra/Module/PID.lean @@ -225,7 +225,7 @@ theorem torsion_by_prime_power_decomposition (hN : Module.IsTorsion' N (Submonoi ⟨(@hN x).choose, by rw [← Quotient.mk_smul, (@hN x).choose_spec, Quotient.mk_zero]⟩ · have hs' := congr_arg (Submodule.map <| mkQ <| R ∙ s j) hs rw [Submodule.map_span, Submodule.map_top, range_mkQ] at hs'; simp only [mkQ_apply] at hs' - simp only [s']; rw [← Function.comp.assoc, Set.range_comp (_ ∘ s), Fin.range_succAbove] + simp only [s']; rw [← Function.comp_assoc, Set.range_comp (_ ∘ s), Fin.range_succAbove] rw [← Set.range_comp, ← Set.insert_image_compl_eq_range _ j, Function.comp_apply, (Quotient.mk_eq_zero _).mpr (Submodule.mem_span_singleton_self _), span_insert_zero] at hs' exact hs' diff --git a/Mathlib/Algebra/Order/Rearrangement.lean b/Mathlib/Algebra/Order/Rearrangement.lean index 6643fbdac7eec..f032d3104e240 100644 --- a/Mathlib/Algebra/Order/Rearrangement.lean +++ b/Mathlib/Algebra/Order/Rearrangement.lean @@ -164,10 +164,10 @@ theorem MonovaryOn.sum_comp_perm_smul_eq_sum_smul_iff (hfg : MonovaryOn f g s) rw [σ.sum_comp' s (fun i j ↦ f i • g j) hσ] congr · convert h.comp_right σ - · rw [comp.assoc, inv_def, symm_comp_self, comp_id] + · rw [comp_assoc, inv_def, symm_comp_self, comp_id] · rw [σ.eq_preimage_iff_image_eq, Set.image_perm hσ] · convert h.comp_right σ.symm - · rw [comp.assoc, self_comp_symm, comp_id] + · rw [comp_assoc, self_comp_symm, comp_id] · rw [σ.symm.eq_preimage_iff_image_eq] exact Set.image_perm hσinv diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index 8945030d7edd1..56989b5600798 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -265,7 +265,7 @@ instance isOpenImmersion_fromSpec : theorem range_fromSpec : Set.range hU.fromSpec.1.base = (U : Set X) := by delta IsAffineOpen.fromSpec; dsimp - rw [Function.comp.assoc, Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ] + rw [Function.comp_assoc, Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ] · exact Subtype.range_coe erw [← coe_comp, ← TopCat.epi_iff_surjective] -- now `erw` after #13170 infer_instance diff --git a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean index d5cce4ded4d53..75f2e43860603 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean @@ -304,7 +304,7 @@ theorem norm_iteratedFDerivWithin_prod_le [DecidableEq ι] [NormOneClass A'] {u (g := (fun v ↦ v.multinomial * ∏ j ∈ insert i u, ‖iteratedFDerivWithin 𝕜 (v.count j) (f j) s x‖) ∘ Sym.toMultiset ∘ Subtype.val ∘ (Finset.symInsertEquiv hi).symm) - (by simp) (by simp only [← comp_apply (g := Finset.symInsertEquiv hi), comp.assoc]; simp)] + (by simp) (by simp only [← comp_apply (g := Finset.symInsertEquiv hi), comp_assoc]; simp)] rw [← Finset.univ_sigma_univ, Finset.sum_sigma, Finset.sum_range] simp only [comp_apply, Finset.symInsertEquiv_symm_apply_coe] refine Finset.sum_le_sum ?_ diff --git a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean index e2f34a6adc71a..1c6738f520fcc 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean @@ -87,7 +87,7 @@ theorem comp_differentiableWithinAt_iff {f : G → E} {s : Set G} {x : G} : ⟨fun H => ?_, fun H => iso.differentiable.differentiableAt.comp_differentiableWithinAt x H⟩ have : DifferentiableWithinAt 𝕜 (iso.symm ∘ iso ∘ f) s x := iso.symm.differentiable.differentiableAt.comp_differentiableWithinAt x H - rwa [← Function.comp.assoc iso.symm iso f, iso.symm_comp_self] at this + rwa [← Function.comp_assoc iso.symm iso f, iso.symm_comp_self] at this theorem comp_differentiableAt_iff {f : G → E} {x : G} : DifferentiableAt 𝕜 (iso ∘ f) x ↔ DifferentiableAt 𝕜 f x := by @@ -107,7 +107,7 @@ theorem comp_hasFDerivWithinAt_iff {f : G → E} {s : Set G} {x : G} {f' : G → HasFDerivWithinAt (iso ∘ f) ((iso : E →L[𝕜] F).comp f') s x ↔ HasFDerivWithinAt f f' s x := by refine ⟨fun H => ?_, fun H => iso.hasFDerivAt.comp_hasFDerivWithinAt x H⟩ have A : f = iso.symm ∘ iso ∘ f := by - rw [← Function.comp.assoc, iso.symm_comp_self] + rw [← Function.comp_assoc, iso.symm_comp_self] rfl have B : f' = (iso.symm : F →L[𝕜] E).comp ((iso : E →L[𝕜] F).comp f') := by rw [← ContinuousLinearMap.comp_assoc, iso.coe_symm_comp_coe, ContinuousLinearMap.id_comp] @@ -174,7 +174,7 @@ theorem comp_right_differentiableWithinAt_iff {f : F → G} {s : Set F} {x : E} apply H.comp (iso x) iso.symm.differentiableWithinAt intro y hy simpa only [mem_preimage, apply_symm_apply] using hy - rwa [Function.comp.assoc, iso.self_comp_symm] at this + rwa [Function.comp_assoc, iso.self_comp_symm] at this theorem comp_right_differentiableAt_iff {f : F → G} {x : E} : DifferentiableAt 𝕜 (f ∘ iso) x ↔ DifferentiableAt 𝕜 f (iso x) := by @@ -198,7 +198,7 @@ theorem comp_right_hasFDerivWithinAt_iff {f : F → G} {s : Set F} {x : E} {f' : refine ⟨fun H => ?_, fun H => H.comp x iso.hasFDerivWithinAt (mapsTo_preimage _ s)⟩ rw [← iso.symm_apply_apply x] at H have A : f = (f ∘ iso) ∘ iso.symm := by - rw [Function.comp.assoc, iso.self_comp_symm] + rw [Function.comp_assoc, iso.self_comp_symm] rfl have B : f' = (f'.comp (iso : E →L[𝕜] F)).comp (iso.symm : F →L[𝕜] E) := by rw [ContinuousLinearMap.comp_assoc, iso.coe_comp_coe_symm, ContinuousLinearMap.comp_id] diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean index b662ec13e36fc..f5790c73a631f 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean @@ -82,7 +82,7 @@ iterated derivative. -/ theorem iteratedFDerivWithin_eq_equiv_comp : iteratedFDerivWithin 𝕜 n f s = ContinuousMultilinearMap.piFieldEquiv 𝕜 (Fin n) F ∘ iteratedDerivWithin n f s := by - rw [iteratedDerivWithin_eq_equiv_comp, ← Function.comp.assoc, LinearIsometryEquiv.self_comp_symm, + rw [iteratedDerivWithin_eq_equiv_comp, ← Function.comp_assoc, LinearIsometryEquiv.self_comp_symm, Function.id_comp] /-- The `n`-th Fréchet derivative applied to a vector `(m 0, ..., m (n-1))` is the derivative @@ -203,7 +203,7 @@ theorem iteratedDeriv_eq_equiv_comp : iteratedDeriv n f = iterated derivative. -/ theorem iteratedFDeriv_eq_equiv_comp : iteratedFDeriv 𝕜 n f = ContinuousMultilinearMap.piFieldEquiv 𝕜 (Fin n) F ∘ iteratedDeriv n f := by - rw [iteratedDeriv_eq_equiv_comp, ← Function.comp.assoc, LinearIsometryEquiv.self_comp_symm, + rw [iteratedDeriv_eq_equiv_comp, ← Function.comp_assoc, LinearIsometryEquiv.self_comp_symm, Function.id_comp] /-- The `n`-th Fréchet derivative applied to a vector `(m 0, ..., m (n-1))` is the derivative diff --git a/Mathlib/Analysis/Convex/Intrinsic.lean b/Mathlib/Analysis/Convex/Intrinsic.lean index d05235e251337..b244bd60d24fb 100644 --- a/Mathlib/Analysis/Convex/Intrinsic.lean +++ b/Mathlib/Analysis/Convex/Intrinsic.lean @@ -250,8 +250,8 @@ theorem image_intrinsicInterior (φ : P →ᵃⁱ[𝕜] Q) (s : Set P) : let f := ((affineSpan 𝕜 s).isometryEquivMap φ).toHomeomorph have : φ.toAffineMap ∘ (↑) ∘ f.symm = (↑) := funext isometryEquivMap.apply_symm_apply rw [intrinsicInterior, intrinsicInterior, ← φ.coe_toAffineMap, ← map_span φ.toAffineMap s, ← this, - ← Function.comp.assoc, image_comp, image_comp, f.symm.image_interior, f.image_symm, - ← preimage_comp, Function.comp.assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, + ← Function.comp_assoc, image_comp, image_comp, f.symm.image_interior, f.image_symm, + ← preimage_comp, Function.comp_assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, Function.comp_id, preimage_comp, φ.injective.preimage_image] @[simp] @@ -263,8 +263,8 @@ theorem image_intrinsicFrontier (φ : P →ᵃⁱ[𝕜] Q) (s : Set P) : let f := ((affineSpan 𝕜 s).isometryEquivMap φ).toHomeomorph have : φ.toAffineMap ∘ (↑) ∘ f.symm = (↑) := funext isometryEquivMap.apply_symm_apply rw [intrinsicFrontier, intrinsicFrontier, ← φ.coe_toAffineMap, ← map_span φ.toAffineMap s, ← this, - ← Function.comp.assoc, image_comp, image_comp, f.symm.image_frontier, f.image_symm, - ← preimage_comp, Function.comp.assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, + ← Function.comp_assoc, image_comp, image_comp, f.symm.image_frontier, f.image_symm, + ← preimage_comp, Function.comp_assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, Function.comp_id, preimage_comp, φ.injective.preimage_image] @[simp] @@ -276,8 +276,8 @@ theorem image_intrinsicClosure (φ : P →ᵃⁱ[𝕜] Q) (s : Set P) : let f := ((affineSpan 𝕜 s).isometryEquivMap φ).toHomeomorph have : φ.toAffineMap ∘ (↑) ∘ f.symm = (↑) := funext isometryEquivMap.apply_symm_apply rw [intrinsicClosure, intrinsicClosure, ← φ.coe_toAffineMap, ← map_span φ.toAffineMap s, ← this, - ← Function.comp.assoc, image_comp, image_comp, f.symm.image_closure, f.image_symm, - ← preimage_comp, Function.comp.assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, + ← Function.comp_assoc, image_comp, image_comp, f.symm.image_closure, f.image_symm, + ← preimage_comp, Function.comp_assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, Function.comp_id, preimage_comp, φ.injective.preimage_image] end AffineIsometry diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean index f34699a4c7f97..b7b5fa601494d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean @@ -598,7 +598,7 @@ theorem continuousAt_arg_coe_angle (h : x ≠ 0) : ContinuousAt ((↑) ∘ arg : · exact Real.Angle.continuous_coe.continuousAt.comp (continuousAt_arg hs) · rw [← Function.comp_id (((↑) : ℝ → Real.Angle) ∘ arg), (Function.funext_iff.2 fun _ => (neg_neg _).symm : (id : ℂ → ℂ) = Neg.neg ∘ Neg.neg), ← - Function.comp.assoc] + Function.comp_assoc] refine ContinuousAt.comp ?_ continuous_neg.continuousAt suffices ContinuousAt (Function.update (((↑) ∘ arg) ∘ Neg.neg : ℂ → Real.Angle) 0 π) (-x) by rwa [continuousAt_update_of_ne (neg_ne_zero.2 h)] at this diff --git a/Mathlib/Combinatorics/HalesJewett.lean b/Mathlib/Combinatorics/HalesJewett.lean index b97bcd5a4cdf7..f02b849012141 100644 --- a/Mathlib/Combinatorics/HalesJewett.lean +++ b/Mathlib/Combinatorics/HalesJewett.lean @@ -150,7 +150,7 @@ def reindex (l : Subspace η α ι) (eη : η ≃ η') (eα : α ≃ α') (eι : protected lemma IsMono.reindex {eη : η ≃ η'} {eα : α ≃ α'} {eι : ι ≃ ι'} {C : (ι → α) → κ} (hl : l.IsMono C) : (l.reindex eη eα eι).IsMono fun x ↦ C <| eα.symm ∘ x ∘ eι := by - simp [reindex_isMono, Function.comp.assoc]; simpa [← Function.comp.assoc] + simp [reindex_isMono, Function.comp_assoc]; simpa [← Function.comp_assoc] end Subspace diff --git a/Mathlib/Data/Fin/Tuple/Sort.lean b/Mathlib/Data/Fin/Tuple/Sort.lean index d53751d03f1f5..6dfe8a11de7e8 100644 --- a/Mathlib/Data/Fin/Tuple/Sort.lean +++ b/Mathlib/Data/Fin/Tuple/Sort.lean @@ -178,7 +178,7 @@ theorem comp_sort_eq_comp_iff_monotone : f ∘ σ = f ∘ sort f ↔ Monotone (f /-- The sorted versions of a tuple `f` and of any permutation of `f` agree. -/ theorem comp_perm_comp_sort_eq_comp_sort : (f ∘ σ) ∘ sort (f ∘ σ) = f ∘ sort f := by - rw [Function.comp.assoc, ← Equiv.Perm.coe_mul] + rw [Function.comp_assoc, ← Equiv.Perm.coe_mul] exact unique_monotone (monotone_sort (f ∘ σ)) (monotone_sort f) /-- If a permutation `f ∘ σ` of the tuple `f` is not the same as `f ∘ sort f`, then `f ∘ σ` diff --git a/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean b/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean index f3cf7b84dd1bf..aeb910c97b9ae 100644 --- a/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean +++ b/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean @@ -102,13 +102,13 @@ protected theorem comp_left_iff {g : α → β} {e : β ≃ᵐ γ} (h : MeasureP MeasurePreserving (e ∘ g) μa μc ↔ MeasurePreserving g μa μb := by refine ⟨fun hg => ?_, fun hg => h.comp hg⟩ convert (MeasurePreserving.symm e h).comp hg - simp [← Function.comp.assoc e.symm e g] + simp [← Function.comp_assoc e.symm e g] protected theorem comp_right_iff {g : α → β} {e : γ ≃ᵐ α} (h : MeasurePreserving e μc μa) : MeasurePreserving (g ∘ e) μc μb ↔ MeasurePreserving g μa μb := by refine ⟨fun hg => ?_, fun hg => hg.comp h⟩ convert hg.comp (MeasurePreserving.symm e h) - simp [Function.comp.assoc g e e.symm] + simp [Function.comp_assoc g e e.symm] protected theorem sigmaFinite {f : α → β} (hf : MeasurePreserving f μa μb) [SigmaFinite μb] : SigmaFinite μa := diff --git a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean index f1f298984aaa0..9feae63ffc666 100644 --- a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean +++ b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean @@ -272,8 +272,8 @@ theorem liftPropWithinAt_indep_chart_aux (he : e ∈ G.maximalAtlas M) (xe : x (xf : g x ∈ f.source) (hf' : f' ∈ G'.maximalAtlas M') (xf' : g x ∈ f'.source) (hgs : ContinuousWithinAt g s x) : P (f ∘ g ∘ e.symm) (e.symm ⁻¹' s) (e x) ↔ P (f' ∘ g ∘ e'.symm) (e'.symm ⁻¹' s) (e' x) := by - rw [← Function.comp.assoc, hG.liftPropWithinAt_indep_chart_source_aux (f ∘ g) he xe he' xe', - Function.comp.assoc, hG.liftPropWithinAt_indep_chart_target_aux xe' hf xf hf' xf' hgs] + rw [← Function.comp_assoc, hG.liftPropWithinAt_indep_chart_source_aux (f ∘ g) he xe he' xe', + Function.comp_assoc, hG.liftPropWithinAt_indep_chart_target_aux xe' hf xf hf' xf' hgs] theorem liftPropWithinAt_indep_chart [HasGroupoid M G] [HasGroupoid M' G'] (he : e ∈ G.maximalAtlas M) (xe : x ∈ e.source) (hf : f ∈ G'.maximalAtlas M') @@ -292,9 +292,9 @@ theorem liftPropWithinAt_indep_chart_source [HasGroupoid M G] (he : e ∈ G.maxi rw [liftPropWithinAt_self_source, liftPropWithinAt_iff', e.symm.continuousWithinAt_iff_continuousWithinAt_comp_right xe, e.symm_symm] refine and_congr Iff.rfl ?_ - rw [Function.comp_apply, e.left_inv xe, ← Function.comp.assoc, + rw [Function.comp_apply, e.left_inv xe, ← Function.comp_assoc, hG.liftPropWithinAt_indep_chart_source_aux (chartAt _ (g x) ∘ g) (chart_mem_maximalAtlas G x) - (mem_chart_source _ x) he xe, Function.comp.assoc] + (mem_chart_source _ x) he xe, Function.comp_assoc] /-- A version of `liftPropWithinAt_indep_chart`, only for the target. -/ theorem liftPropWithinAt_indep_chart_target [HasGroupoid M' G'] (hf : f ∈ G'.maximalAtlas M') diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean index 5161781aac7d7..908659feaf54a 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -156,7 +156,7 @@ theorem tangentMap_chart_symm {p : TangentBundle I M} {q : TangentBundle I H} lemma mfderiv_chartAt_eq_tangentCoordChange {x y : M} (hsrc : x ∈ (chartAt H y).source) : mfderiv I I (chartAt H y) x = tangentCoordChange I x y x := by have := mdifferentiableAt_atlas I (ChartedSpace.chart_mem_atlas _) hsrc - simp [mfderiv, if_pos this, Function.comp.assoc] + simp [mfderiv, if_pos this, Function.comp_assoc] end Charts diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index b252d909311ac..5ed443618c56c 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -309,7 +309,7 @@ theorem symm_continuousWithinAt_comp_right_iff {X} [TopologicalSpace X] {f : H · have := h.comp I.continuousWithinAt (mapsTo_preimage _ _) simp_rw [preimage_inter, preimage_preimage, I.left_inv, preimage_id', preimage_range, inter_univ] at this - rwa [Function.comp.assoc, I.symm_comp_self] at this + rwa [Function.comp_assoc, I.symm_comp_self] at this · rw [← I.left_inv x] at h; exact h.comp I.continuousWithinAt_symm inter_subset_left protected theorem locallyCompactSpace [LocallyCompactSpace E] (I : ModelWithCorners 𝕜 E H) : diff --git a/Mathlib/LinearAlgebra/Alternating/Basic.lean b/Mathlib/LinearAlgebra/Alternating/Basic.lean index 3c306db16e0ea..1c884e7f3cd86 100644 --- a/Mathlib/LinearAlgebra/Alternating/Basic.lean +++ b/Mathlib/LinearAlgebra/Alternating/Basic.lean @@ -603,8 +603,8 @@ theorem map_perm [DecidableEq ι] [Fintype ι] (v : ι → M) (σ : Equiv.Perm -- Porting note: `apply` → `induction'` induction' σ using Equiv.Perm.swap_induction_on' with s x y hxy hI · simp - · -- Porting note: `← Function.comp.assoc` & `-Equiv.Perm.sign_swap'` are required. - simpa [← Function.comp.assoc, g.map_swap (v ∘ s) hxy, + · -- Porting note: `← Function.comp_assoc` & `-Equiv.Perm.sign_swap'` are required. + simpa [← Function.comp_assoc, g.map_swap (v ∘ s) hxy, Equiv.Perm.sign_swap hxy, -Equiv.Perm.sign_swap'] using hI theorem map_congr_perm [DecidableEq ι] [Fintype ι] (σ : Equiv.Perm ι) : diff --git a/Mathlib/LinearAlgebra/Determinant.lean b/Mathlib/LinearAlgebra/Determinant.lean index 984b62e9b92a4..ce891c2dddd94 100644 --- a/Mathlib/LinearAlgebra/Determinant.lean +++ b/Mathlib/LinearAlgebra/Determinant.lean @@ -558,7 +558,7 @@ theorem Basis.det_reindex' {ι' : Type*} [Fintype ι'] [DecidableEq ι'] (b : Ba theorem Basis.det_reindex_symm {ι' : Type*} [Fintype ι'] [DecidableEq ι'] (b : Basis ι R M) (v : ι → M) (e : ι' ≃ ι) : (b.reindex e.symm).det (v ∘ e) = b.det v := by - rw [Basis.det_reindex, Function.comp.assoc, e.self_comp_symm, Function.comp_id] + rw [Basis.det_reindex, Function.comp_assoc, e.self_comp_symm, Function.comp_id] @[simp] theorem Basis.det_map (b : Basis ι R M) (f : M ≃ₗ[R] M') (v : ι → M') : diff --git a/Mathlib/LinearAlgebra/LinearDisjoint.lean b/Mathlib/LinearAlgebra/LinearDisjoint.lean index 20c9c3b4316e4..3eb097c1e65c0 100644 --- a/Mathlib/LinearAlgebra/LinearDisjoint.lean +++ b/Mathlib/LinearAlgebra/LinearDisjoint.lean @@ -311,7 +311,7 @@ theorem linearIndependent_left_of_flat (H : M.LinearDisjoint N) [Module.Flat R N {ι : Type*} {m : ι → M} (hm : LinearIndependent R m) : LinearMap.ker (mulLeftMap N m) = ⊥ := by refine LinearMap.ker_eq_bot_of_injective ?_ classical simp_rw [mulLeftMap_eq_mulMap_comp, LinearMap.coe_comp, LinearEquiv.coe_coe, - ← Function.comp.assoc, EquivLike.injective_comp] + ← Function.comp_assoc, EquivLike.injective_comp] rw [LinearIndependent, LinearMap.ker_eq_bot] at hm exact H.injective.comp (Module.Flat.rTensor_preserves_injective_linearMap (M := N) _ hm) @@ -332,7 +332,7 @@ theorem linearIndependent_right_of_flat (H : M.LinearDisjoint N) [Module.Flat R {ι : Type*} {n : ι → N} (hn : LinearIndependent R n) : LinearMap.ker (mulRightMap M n) = ⊥ := by refine LinearMap.ker_eq_bot_of_injective ?_ classical simp_rw [mulRightMap_eq_mulMap_comp, LinearMap.coe_comp, LinearEquiv.coe_coe, - ← Function.comp.assoc, EquivLike.injective_comp] + ← Function.comp_assoc, EquivLike.injective_comp] rw [LinearIndependent, LinearMap.ker_eq_bot] at hn exact H.injective.comp (Module.Flat.lTensor_preserves_injective_linearMap (M := M) _ hn) diff --git a/Mathlib/LinearAlgebra/Matrix/Block.lean b/Mathlib/LinearAlgebra/Matrix/Block.lean index c998bad25a879..8432d56b10b42 100644 --- a/Mathlib/LinearAlgebra/Matrix/Block.lean +++ b/Mathlib/LinearAlgebra/Matrix/Block.lean @@ -62,7 +62,7 @@ theorem blockTriangular_reindex_iff {b : n → α} {e : m ≃ n} : · convert h.submatrix simp only [reindex_apply, submatrix_submatrix, submatrix_id_id, Equiv.symm_comp_self] · convert h.submatrix - simp only [comp.assoc b e e.symm, Equiv.self_comp_symm, comp_id] + simp only [comp_assoc b e e.symm, Equiv.self_comp_symm, comp_id] protected theorem BlockTriangular.transpose : M.BlockTriangular b → Mᵀ.BlockTriangular (toDual ∘ b) := diff --git a/Mathlib/LinearAlgebra/RootSystem/Hom.lean b/Mathlib/LinearAlgebra/RootSystem/Hom.lean index 2602934fad93e..f70d0830fdaee 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Hom.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Hom.lean @@ -74,11 +74,11 @@ def Hom.comp {ι₁ M₁ N₁ ι₂ M₂ N₂ : Type*} [AddCommGroup M₁] [Modu root_weightMap := by ext i simp only [LinearMap.coe_comp, Equiv.coe_trans] - rw [comp.assoc, f.root_weightMap, ← comp.assoc, g.root_weightMap, comp.assoc] + rw [comp_assoc, f.root_weightMap, ← comp_assoc, g.root_weightMap, comp_assoc] coroot_coweightMap := by ext i simp only [LinearMap.coe_comp, Equiv.symm_trans_apply] - rw [comp.assoc, g.coroot_coweightMap, ← comp.assoc, f.coroot_coweightMap, comp.assoc] + rw [comp_assoc, g.coroot_coweightMap, ← comp_assoc, f.coroot_coweightMap, comp_assoc] simp @[simp] diff --git a/Mathlib/Logic/Function/Basic.lean b/Mathlib/Logic/Function/Basic.lean index a7dcb29d9f608..21435518020b1 100644 --- a/Mathlib/Logic/Function/Basic.lean +++ b/Mathlib/Logic/Function/Basic.lean @@ -329,7 +329,7 @@ theorem LeftInverse.eq_rightInverse {f : α → β} {g₁ g₂ : β → α} (h (h₂ : RightInverse g₂ f) : g₁ = g₂ := calc g₁ = g₁ ∘ f ∘ g₂ := by rw [h₂.comp_eq_id, comp_id] - _ = g₂ := by rw [← comp.assoc, h₁.comp_eq_id, id_comp] + _ = g₂ := by rw [← comp_assoc, h₁.comp_eq_id, id_comp] attribute [local instance] Classical.propDecidable @@ -672,7 +672,7 @@ theorem Injective.surjective_comp_right [Nonempty γ] (hf : Injective f) : theorem Bijective.comp_right (hf : Bijective f) : Bijective fun g : β → γ ↦ g ∘ f := ⟨hf.surjective.injective_comp_right, fun g ↦ ⟨g ∘ surjInv hf.surjective, - by simp only [comp.assoc g _ f, (leftInverse_surjInv hf).comp_eq_id, comp_id]⟩⟩ + by simp only [comp_assoc g _ f, (leftInverse_surjInv hf).comp_eq_id, comp_id]⟩⟩ end Extend diff --git a/Mathlib/Logic/Function/Defs.lean b/Mathlib/Logic/Function/Defs.lean index 72aa534f806b9..78f83b38c66c0 100644 --- a/Mathlib/Logic/Function/Defs.lean +++ b/Mathlib/Logic/Function/Defs.lean @@ -88,8 +88,9 @@ theorem comp_id (f : α → β) : f ∘ id = f := rfl @[deprecated (since := "2024-01-14")] alias right_id := comp_id @[deprecated (since := "2024-01-14")] alias comp.right_id := comp_id -theorem comp.assoc (f : φ → δ) (g : β → φ) (h : α → β) : (f ∘ g) ∘ h = f ∘ g ∘ h := +theorem comp_assoc (f : φ → δ) (g : β → φ) (h : α → β) : (f ∘ g) ∘ h = f ∘ g ∘ h := rfl +@[deprecated (since := "2024-09-24")] alias comp.assoc := comp_assoc @[deprecated (since := "2024-01-14")] alias comp_const_right := comp_const diff --git a/Mathlib/MeasureTheory/Function/Jacobian.lean b/Mathlib/MeasureTheory/Function/Jacobian.lean index 2aa9266c5528d..3b9bc2e1d765d 100644 --- a/Mathlib/MeasureTheory/Function/Jacobian.lean +++ b/Mathlib/MeasureTheory/Function/Jacobian.lean @@ -1155,7 +1155,7 @@ theorem integrableOn_image_iff_integrableOn_abs_det_fderiv_smul (hs : Measurable IntegrableOn g (f '' s) μ ↔ IntegrableOn (fun x => |(f' x).det| • g (f x)) s μ := by rw [IntegrableOn, ← restrict_map_withDensity_abs_det_fderiv_eq_addHaar μ hs hf' hf, (measurableEmbedding_of_fderivWithin hs hf' hf).integrable_map_iff] - simp only [Set.restrict_eq, ← Function.comp.assoc, ENNReal.ofReal] + simp only [Set.restrict_eq, ← Function.comp_assoc, ENNReal.ofReal] rw [← (MeasurableEmbedding.subtype_coe hs).integrable_map_iff, map_comap_subtype_coe hs, restrict_withDensity hs, integrable_withDensity_iff_integrable_coe_smul₀] · simp_rw [IntegrableOn, Real.coe_toNNReal _ (abs_nonneg _), Function.comp_apply] diff --git a/Mathlib/ModelTheory/Basic.lean b/Mathlib/ModelTheory/Basic.lean index 0643bc17fdebe..e19707451b558 100644 --- a/Mathlib/ModelTheory/Basic.lean +++ b/Mathlib/ModelTheory/Basic.lean @@ -474,7 +474,7 @@ def comp (hnp : N ↪[L] P) (hmn : M ↪[L] N) : M ↪[L] P where -- Porting note: should be done by autoparam? map_fun' := by intros; simp only [Function.comp_apply, map_fun]; trivial -- Porting note: should be done by autoparam? - map_rel' := by intros; rw [Function.comp.assoc, map_rel, map_rel] + map_rel' := by intros; rw [Function.comp_assoc, map_rel, map_rel] @[simp] theorem comp_apply (g : N ↪[L] P) (f : M ↪[L] N) (x : M) : g.comp f x = g (f x) := @@ -551,11 +551,11 @@ def symm (f : M ≃[L] N) : N ≃[L] M := simp only [Equiv.toFun_as_coe] rw [Equiv.symm_apply_eq] refine Eq.trans ?_ (f.map_fun' f' (f.toEquiv.symm ∘ x)).symm - rw [← Function.comp.assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.id_comp] + rw [← Function.comp_assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.id_comp] map_rel' := fun n r {x} => by simp only [Equiv.toFun_as_coe] refine (f.map_rel' r (f.toEquiv.symm ∘ x)).symm.trans ?_ - rw [← Function.comp.assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.id_comp] } + rw [← Function.comp_assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.id_comp] } instance hasCoeToFun : CoeFun (M ≃[L] N) fun _ => M → N := DFunLike.hasCoeToFun @@ -648,7 +648,7 @@ def comp (hnp : N ≃[L] P) (hmn : M ≃[L] N) : M ≃[L] P := -- Porting note: should be done by autoparam? map_fun' := by intros; simp only [Function.comp_apply, map_fun]; trivial -- Porting note: should be done by autoparam? - map_rel' := by intros; rw [Function.comp.assoc, map_rel, map_rel] } + map_rel' := by intros; rw [Function.comp_assoc, map_rel, map_rel] } @[simp] theorem comp_apply (g : N ≃[L] P) (f : M ≃[L] N) (x : M) : g.comp f x = g (f x) := @@ -830,8 +830,8 @@ def inducedStructureEquiv (e : M ≃ N) : @Language.Equiv L M N _ (inducedStruct letI : L.Structure N := inducedStructure e exact { e with - map_fun' := @fun n f x => by simp [← Function.comp.assoc e.symm e x] - map_rel' := @fun n r x => by simp [← Function.comp.assoc e.symm e x] } + map_fun' := @fun n f x => by simp [← Function.comp_assoc e.symm e x] + map_rel' := @fun n r x => by simp [← Function.comp_assoc e.symm e x] } @[simp] theorem toEquiv_inducedStructureEquiv (e : M ≃ N) : diff --git a/Mathlib/ModelTheory/DirectLimit.lean b/Mathlib/ModelTheory/DirectLimit.lean index a9c1fe39191e1..3a74358878660 100644 --- a/Mathlib/ModelTheory/DirectLimit.lean +++ b/Mathlib/ModelTheory/DirectLimit.lean @@ -353,13 +353,13 @@ def lift (g : ∀ i, G i ↪[L] P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i map_fun' F x := by obtain ⟨i, y, rfl⟩ := exists_quotient_mk'_sigma_mk'_eq G f x change _ = funMap F (Quotient.lift _ _ ∘ Quotient.mk _ ∘ Structure.Sigma.mk f i ∘ y) - rw [funMap_quotient_mk'_sigma_mk', ← Function.comp.assoc, Quotient.lift_comp_mk] + rw [funMap_quotient_mk'_sigma_mk', ← Function.comp_assoc, Quotient.lift_comp_mk] simp only [Quotient.lift_mk, Embedding.map_fun] rfl map_rel' R x := by obtain ⟨i, y, rfl⟩ := exists_quotient_mk'_sigma_mk'_eq G f x change RelMap R (Quotient.lift _ _ ∘ Quotient.mk _ ∘ Structure.Sigma.mk f i ∘ y) ↔ _ - rw [relMap_quotient_mk'_sigma_mk' G f, ← (g i).map_rel R y, ← Function.comp.assoc, + rw [relMap_quotient_mk'_sigma_mk' G f, ← (g i).map_rel R y, ← Function.comp_assoc, Quotient.lift_comp_mk] rfl diff --git a/Mathlib/ModelTheory/ElementaryMaps.lean b/Mathlib/ModelTheory/ElementaryMaps.lean index ea469044e0dc8..54428842a22a5 100644 --- a/Mathlib/ModelTheory/ElementaryMaps.lean +++ b/Mathlib/ModelTheory/ElementaryMaps.lean @@ -79,12 +79,12 @@ theorem map_boundedFormula (f : M ↪ₑ[L] N) {α : Type*} {n : ℕ} (φ : L.Bo f.map_formula' ((φ.restrictFreeVar id).toFormula.relabel (Fintype.equivFin _)) (Sum.elim (v ∘ (↑)) xs ∘ (Fintype.equivFin _).symm) simp only [Formula.realize_relabel, BoundedFormula.realize_toFormula, iff_eq_eq] at h - rw [← Function.comp.assoc _ _ (Fintype.equivFin _).symm, - Function.comp.assoc _ (Fintype.equivFin _).symm (Fintype.equivFin _), - _root_.Equiv.symm_comp_self, Function.comp_id, Function.comp.assoc, Sum.elim_comp_inl, - Function.comp.assoc _ _ Sum.inr, Sum.elim_comp_inr, ← Function.comp.assoc] at h + rw [← Function.comp_assoc _ _ (Fintype.equivFin _).symm, + Function.comp_assoc _ (Fintype.equivFin _).symm (Fintype.equivFin _), + _root_.Equiv.symm_comp_self, Function.comp_id, Function.comp_assoc, Sum.elim_comp_inl, + Function.comp_assoc _ _ Sum.inr, Sum.elim_comp_inr, ← Function.comp_assoc] at h refine h.trans ?_ - erw [Function.comp.assoc _ _ (Fintype.equivFin _), _root_.Equiv.symm_comp_self, + erw [Function.comp_assoc _ _ (Fintype.equivFin _), _root_.Equiv.symm_comp_self, Function.comp_id, Sum.elim_comp_inl, Sum.elim_comp_inr (v ∘ Subtype.val) xs, ← Set.inclusion_eq_id (s := (BoundedFormula.freeVarFinset φ : Set α)) Set.Subset.rfl, BoundedFormula.realize_restrictFreeVar Set.Subset.rfl] diff --git a/Mathlib/ModelTheory/Syntax.lean b/Mathlib/ModelTheory/Syntax.lean index c302df830a56f..fb5f3691aab1a 100644 --- a/Mathlib/ModelTheory/Syntax.lean +++ b/Mathlib/ModelTheory/Syntax.lean @@ -418,7 +418,7 @@ theorem castLE_castLE {k m n} (km : k ≤ m) (mn : m ≤ n) (φ : L.BoundedFormu | rel => intros simp only [castLE, eq_self_iff_true, heq_iff_eq] - rw [← Function.comp.assoc, Term.relabel_comp_relabel] + rw [← Function.comp_assoc, Term.relabel_comp_relabel] simp | imp _ _ ih1 ih2 => simp [ih1, ih2] | all _ ih3 => intros; simp only [castLE, ih3] diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean index 9642c81b12ef4..bc17c8afdc322 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean @@ -204,7 +204,7 @@ protected theorem Multipliable.map_iff_of_leftInverse [CommMonoid γ] [Topologic Multipliable (g ∘ f) ↔ Multipliable f := ⟨fun h ↦ by have := h.map _ hg' - rwa [← Function.comp.assoc, hinv.id] at this, fun h ↦ h.map _ hg⟩ + rwa [← Function.comp_assoc, hinv.id] at this, fun h ↦ h.map _ hg⟩ @[to_additive] theorem Multipliable.map_tprod [CommMonoid γ] [TopologicalSpace γ] [T2Space γ] (hf : Multipliable f) diff --git a/Mathlib/Topology/Category/CompHaus/Projective.lean b/Mathlib/Topology/Category/CompHaus/Projective.lean index 17bdb7ef5c926..97532c9b45d96 100644 --- a/Mathlib/Topology/Category/CompHaus/Projective.lean +++ b/Mathlib/Topology/Category/CompHaus/Projective.lean @@ -52,7 +52,7 @@ instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X) w let g'' : ContinuousMap Y Z := g have : g'' ∘ g' = id := hg'.comp_eq_id -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, id_comp] + erw [comp_assoc, ultrafilter_extend_extends, ← comp_assoc, this, id_comp] /-- For any compact Hausdorff space `X`, the natural map `Ultrafilter X → X` is a projective presentation. -/ diff --git a/Mathlib/Topology/Category/Profinite/Nobeling.lean b/Mathlib/Topology/Category/Profinite/Nobeling.lean index b666e7f0d9593..d9f4b3c3fea60 100644 --- a/Mathlib/Topology/Category/Profinite/Nobeling.lean +++ b/Mathlib/Topology/Category/Profinite/Nobeling.lean @@ -412,7 +412,7 @@ theorem evalFacProps {l : Products I} (J K : I → Prop) have : l.eval (π C J) ∘ Homeomorph.setCongr (proj_eq_of_subset C J K hJK) = l.eval (π (π C K) J) := by ext; simp [Homeomorph.setCongr, Products.eval_eq] - rw [ProjRestricts, ← Function.comp.assoc, this, ← evalFacProp (π C K) J h] + rw [ProjRestricts, ← Function.comp_assoc, this, ← evalFacProp (π C K) J h] theorem prop_of_isGood {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)] (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by @@ -1043,7 +1043,7 @@ theorem smaller_mono {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂) : smaller C o₁ ext x rw [eval, ← Products.eval_πs' _ h (Products.prop_of_isGood C _ gl), eval] · rw [← LocallyConstant.coe_inj, coe_πs C o₂, ← LocallyConstant.toFun_eq_coe, coe_πs', - Function.comp.assoc, projRestricts_comp_projRestrict C _, coe_πs] + Function.comp_assoc, projRestricts_comp_projRestrict C _, coe_πs] rfl end GoodProducts diff --git a/Mathlib/Topology/Category/Profinite/Projective.lean b/Mathlib/Topology/Category/Profinite/Projective.lean index becda45ececde..98eb2deeef7fc 100644 --- a/Mathlib/Topology/Category/Profinite/Projective.lean +++ b/Mathlib/Topology/Category/Profinite/Projective.lean @@ -51,7 +51,7 @@ instance projective_ultrafilter (X : Type u) : Projective (of <| Ultrafilter X) let g'' : ContinuousMap Y Z := g have : g'' ∘ g' = id := hg'.comp_eq_id -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, id_comp] + erw [comp_assoc, ultrafilter_extend_extends, ← comp_assoc, this, id_comp] /-- For any profinite `X`, the natural map `Ultrafilter X → X` is a projective presentation. -/ def projectivePresentation (X : Profinite.{u}) : ProjectivePresentation X where diff --git a/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean b/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean index 75ee84190369c..35693a3a1dedc 100644 --- a/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean @@ -60,7 +60,7 @@ theorem effectiveEpi_iff_quotientMap {B X : TopCat.{u}} (π : X ⟶ B) : let F := parallelPair hπ.left hπ.right let i : B ≅ colimit F := hπ.isColimit.coconePointUniqueUpToIso (colimit.isColimit _) suffices QuotientMap (homeoOfIso i ∘ π) by - simpa [← Function.comp.assoc] using (homeoOfIso i).symm.quotientMap.comp this + simpa [← Function.comp_assoc] using (homeoOfIso i).symm.quotientMap.comp this constructor /- Effective epimorphisms are epimorphisms and epimorphisms in `TopCat` are surjective. -/ · change Function.Surjective (π ≫ i.hom) diff --git a/Mathlib/Topology/ExtremallyDisconnected.lean b/Mathlib/Topology/ExtremallyDisconnected.lean index a5d3b08560a46..f81a6b4448fd2 100644 --- a/Mathlib/Topology/ExtremallyDisconnected.lean +++ b/Mathlib/Topology/ExtremallyDisconnected.lean @@ -88,7 +88,7 @@ theorem StoneCech.projective [DiscreteTopology X] : CompactT2.Projective (StoneC let h : StoneCech X → Y := stoneCechExtend ht have hh : Continuous h := continuous_stoneCechExtend ht refine ⟨h, hh, denseRange_stoneCechUnit.equalizer (hg.comp hh) hf ?_⟩ - rw [comp.assoc, stoneCechExtend_extends ht, ← comp.assoc, hs, id_comp] + rw [comp_assoc, stoneCechExtend_extends ht, ← comp_assoc, hs, id_comp] protected theorem CompactT2.Projective.extremallyDisconnected [CompactSpace X] [T2Space X] (h : CompactT2.Projective X) : ExtremallyDisconnected X := by @@ -271,7 +271,7 @@ protected theorem CompactT2.ExtremallyDisconnected.projective [ExtremallyDisconn have π₂_cont : Continuous π₂ := continuous_snd.comp continuous_subtype_val refine ⟨E.restrict π₂ ∘ ρ'.symm, ⟨π₂_cont.continuousOn.restrict.comp ρ'.symm.continuous, ?_⟩⟩ suffices f ∘ E.restrict π₂ = φ ∘ ρ' by - rw [← comp.assoc, this, comp.assoc, Homeomorph.self_comp_symm, comp_id] + rw [← comp_assoc, this, comp_assoc, Homeomorph.self_comp_symm, comp_id] ext x exact x.val.mem.symm diff --git a/Mathlib/Topology/Homeomorph.lean b/Mathlib/Topology/Homeomorph.lean index 3a5abc02d2bd4..bc14d3525fda0 100644 --- a/Mathlib/Topology/Homeomorph.lean +++ b/Mathlib/Topology/Homeomorph.lean @@ -451,14 +451,14 @@ theorem comp_continuousWithinAt_iff (h : X ≃ₜ Y) (f : Z → X) (s : Set Z) ( theorem comp_isOpenMap_iff (h : X ≃ₜ Y) {f : Z → X} : IsOpenMap (h ∘ f) ↔ IsOpenMap f := by refine ⟨?_, fun hf => h.isOpenMap.comp hf⟩ intro hf - rw [← Function.id_comp f, ← h.symm_comp_self, Function.comp.assoc] + rw [← Function.id_comp f, ← h.symm_comp_self, Function.comp_assoc] exact h.symm.isOpenMap.comp hf @[simp] theorem comp_isOpenMap_iff' (h : X ≃ₜ Y) {f : Y → Z} : IsOpenMap (f ∘ h) ↔ IsOpenMap f := by refine ⟨?_, fun hf => hf.comp h.isOpenMap⟩ intro hf - rw [← Function.comp_id f, ← h.self_comp_symm, ← Function.comp.assoc] + rw [← Function.comp_id f, ← h.self_comp_symm, ← Function.comp_assoc] exact hf.comp h.symm.isOpenMap /-- A homeomorphism `h : X ≃ₜ Y` lifts to a homeomorphism between subtypes corresponding to From c7d6577ad9a4110f04f2ba10501f5508a2e9e6f2 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 24 Sep 2024 16:18:41 +0000 Subject: [PATCH 133/170] fix: do not break multiplication notation (#17101) Without this change, `import Mathlib` breaks `_*_` as notation for `_ * _`. [Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Bad.20TopCat.2EPresheaf.2Epushforward.20notation/near/472520318) Co-authored-by: Eric Wieser --- Mathlib/Topology/Sheaves/Functors.lean | 2 ++ Mathlib/Topology/Sheaves/Presheaf.lean | 4 ++-- Mathlib/Topology/Sheaves/Skyscraper.lean | 1 + Mathlib/Topology/Sheaves/Stalks.lean | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Mathlib/Topology/Sheaves/Functors.lean b/Mathlib/Topology/Sheaves/Functors.lean index ee393d3948d1a..d246fbdbe9fcc 100644 --- a/Mathlib/Topology/Sheaves/Functors.lean +++ b/Mathlib/Topology/Sheaves/Functors.lean @@ -34,6 +34,8 @@ open CategoryTheory.Limits open TopologicalSpace +open scoped AlgebraicGeometry + variable {C : Type u} [Category.{v} C] variable {X Y : TopCat.{w}} (f : X ⟶ Y) variable ⦃ι : Type w⦄ {U : ι → Opens Y} diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index c3fda4efb382e..6b2b727509484 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -153,9 +153,9 @@ variable (C) def pushforward {X Y : TopCat.{w}} (f : X ⟶ Y) : X.Presheaf C ⥤ Y.Presheaf C := (whiskeringLeft _ _ _).obj (Opens.map f).op -set_option quotPrecheck false in /-- push forward of a presheaf -/ -notation f:80 " _* " P:81 => (pushforward _ f).obj P +scoped[AlgebraicGeometry] notation f:80 " _* " P:81 => + Prefunctor.obj (Functor.toPrefunctor (TopCat.Presheaf.pushforward _ f)) P @[simp] theorem pushforward_map_app' {X Y : TopCat.{w}} (f : X ⟶ Y) {ℱ 𝒢 : X.Presheaf C} (α : ℱ ⟶ 𝒢) diff --git a/Mathlib/Topology/Sheaves/Skyscraper.lean b/Mathlib/Topology/Sheaves/Skyscraper.lean index f70fab0697f9e..9cdd092a962a9 100644 --- a/Mathlib/Topology/Sheaves/Skyscraper.lean +++ b/Mathlib/Topology/Sheaves/Skyscraper.lean @@ -34,6 +34,7 @@ TODO: generalize universe level when calculating stalks, after generalizing univ noncomputable section open TopologicalSpace TopCat CategoryTheory CategoryTheory.Limits Opposite +open scoped AlgebraicGeometry universe u v w diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index da3cfda14b8b4..d1e8867ba7f1a 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -60,6 +60,8 @@ open TopologicalSpace open Opposite +open scoped AlgebraicGeometry + variable {C : Type u} [Category.{v} C] variable [HasColimits.{v} C] variable {X Y Z : TopCat.{v}} From 6d0638698bd9e481c26abc2827b7d7a53ebbc115 Mon Sep 17 00:00:00 2001 From: Yongle Hu Date: Tue, 24 Sep 2024 17:42:50 +0000 Subject: [PATCH 134/170] feat(RingTheory/DedekindDomain): `IsDedekindDomainDvr` implies `IsDedekindDomain` (#16631) Prove that `IsDedekindDomainDvr` implies `IsDedekindDomain`, i.e., if an integral domain is Noetherian, and the localization at every nonzero prime is a discrete valuation ring, then it is a Dedekind domain. Co-authored-by: Yongle Hu @mbkybky Co-authored-by: Jiedong Jiang @jjdishere - [x] depends on: #16558 Co-authored-by: Hu Yongle <2065545849@qq.com> Co-authored-by: Yongle Hu <140475041+mbkybky@users.noreply.github.com> --- Mathlib/RingTheory/DedekindDomain/Dvr.lean | 57 ++++++++++++++++------ 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/Mathlib/RingTheory/DedekindDomain/Dvr.lean b/Mathlib/RingTheory/DedekindDomain/Dvr.lean index 04b1f0a1bc959..2edc66bfc7bfa 100644 --- a/Mathlib/RingTheory/DedekindDomain/Dvr.lean +++ b/Mathlib/RingTheory/DedekindDomain/Dvr.lean @@ -1,18 +1,16 @@ /- Copyright (c) 2020 Kenji Nakagawa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kenji Nakagawa, Anne Baanen, Filippo A. E. Nuccio +Authors: Kenji Nakagawa, Anne Baanen, Filippo A. E. Nuccio, Yongle Hu -/ -import Mathlib.RingTheory.Localization.LocalizationLocalization -import Mathlib.RingTheory.Localization.Submodule import Mathlib.RingTheory.DiscreteValuationRing.TFAE +import Mathlib.RingTheory.LocalProperties.IntegrallyClosed /-! # Dedekind domains This file defines an equivalent notion of a Dedekind domain (or Dedekind ring), -namely a Noetherian integral domain where the localization at all nonzero prime ideals is a DVR -(TODO: and shows that implies the main definition). +namely a Noetherian integral domain where the localization at all nonzero prime ideals is a DVR. ## Main definitions @@ -53,10 +51,8 @@ open scoped nonZeroDivisors Polynomial localization at every nonzero prime is a discrete valuation ring. This is equivalent to `IsDedekindDomain`. -TODO: prove the equivalence. -/ -structure IsDedekindDomainDvr : Prop where - isNoetherianRing : IsNoetherianRing A +class IsDedekindDomainDvr extends IsNoetherian A A : Prop where is_dvr_at_nonzero_prime : ∀ P ≠ (⊥ : Ideal A), ∀ _ : P.IsPrime, DiscreteValuationRing (Localization.AtPrime P) @@ -94,7 +90,7 @@ theorem IsLocalization.isDedekindDomain [IsDedekindDomain A] {M : Submonoid A} ( IsFractionRing.isFractionRing_of_isDomain_of_isLocalization M _ _ refine (isDedekindDomain_iff _ (FractionRing A)).mpr ⟨?_, ?_, ?_, ?_⟩ · infer_instance - · exact IsLocalization.isNoetherianRing M _ (by infer_instance) + · exact IsLocalization.isNoetherianRing M _ inferInstance · exact Ring.DimensionLEOne.localization Aₘ hM · intro x hx obtain ⟨⟨y, y_mem⟩, hy⟩ := hx.exists_multiple_integral_of_isLocalization M _ @@ -109,8 +105,12 @@ theorem IsLocalization.AtPrime.isDedekindDomain [IsDedekindDomain A] (P : Ideal IsDedekindDomain Aₘ := IsLocalization.isDedekindDomain A P.primeCompl_le_nonZeroDivisors Aₘ +instance Localization.AtPrime.isDedekindDomain [IsDedekindDomain A] (P : Ideal A) [P.IsPrime] : + IsDedekindDomain (Localization.AtPrime P) := + IsLocalization.AtPrime.isDedekindDomain A P _ + theorem IsLocalization.AtPrime.not_isField {P : Ideal A} (hP : P ≠ ⊥) [pP : P.IsPrime] (Aₘ : Type*) - [CommRing Aₘ] [Algebra A Aₘ] [IsLocalization.AtPrime Aₘ P] : ¬IsField Aₘ := by + [CommRing Aₘ] [Algebra A Aₘ] [IsLocalization.AtPrime Aₘ P] : ¬ IsField Aₘ := by intro h letI := h.toField obtain ⟨x, x_mem, x_ne⟩ := P.ne_bot_iff.mp hP @@ -139,7 +139,36 @@ theorem IsLocalization.AtPrime.discreteValuationRing_of_dedekind_domain [IsDedek /-- Dedekind domains, in the sense of Noetherian integrally closed domains of Krull dimension ≤ 1, are also Dedekind domains in the sense of Noetherian domains where the localization at every nonzero prime ideal is a DVR. -/ -theorem IsDedekindDomain.isDedekindDomainDvr [IsDedekindDomain A] : IsDedekindDomainDvr A := - { isNoetherianRing := IsDedekindRing.toIsNoetherian - is_dvr_at_nonzero_prime := fun _ hP _ => - IsLocalization.AtPrime.discreteValuationRing_of_dedekind_domain A hP _ } +instance IsDedekindDomain.isDedekindDomainDvr [IsDedekindDomain A] : IsDedekindDomainDvr A where + is_dvr_at_nonzero_prime := fun _ hP _ => + IsLocalization.AtPrime.discreteValuationRing_of_dedekind_domain A hP _ + +instance IsDedekindDomainDvr.ring_dimensionLEOne [h : IsDedekindDomainDvr A] : + Ring.DimensionLEOne A where + maximalOfPrime := by + intro p hp hpp + rcases p.exists_le_maximal (Ideal.IsPrime.ne_top hpp) with ⟨q, hq, hpq⟩ + let f := (IsLocalization.orderIsoOfPrime q.primeCompl (Localization.AtPrime q)).symm + let P := f ⟨p, hpp, hpq.disjoint_compl_left⟩ + let Q := f ⟨q, hq.isPrime, Set.disjoint_left.mpr fun _ a => a⟩ + have hinj : Function.Injective (algebraMap A (Localization.AtPrime q)) := + IsLocalization.injective (Localization.AtPrime q) q.primeCompl_le_nonZeroDivisors + have hp1 : P.1 ≠ ⊥ := fun x => hp ((p.map_eq_bot_iff_of_injective hinj).mp x) + have hq1 : Q.1 ≠ ⊥ := + fun x => (ne_bot_of_le_ne_bot hp hpq) ((q.map_eq_bot_iff_of_injective hinj).mp x) + rcases (DiscreteValuationRing.iff_pid_with_one_nonzero_prime (Localization.AtPrime q)).mp + (h.is_dvr_at_nonzero_prime q (ne_bot_of_le_ne_bot hp hpq) hq.isPrime) with ⟨_, huq⟩ + rw [show p = q from Subtype.val_inj.mpr <| f.injective <| + Subtype.val_inj.mp (huq.unique ⟨hp1, P.2⟩ ⟨hq1, Q.2⟩)] + exact hq + +instance IsDedekindDomainDvr.isIntegrallyClosed [h : IsDedekindDomainDvr A] : + IsIntegrallyClosed A := + IsIntegrallyClosed.of_localization_maximal <| fun p hp0 hpm => + let ⟨_, _⟩ := (DiscreteValuationRing.iff_pid_with_one_nonzero_prime (Localization.AtPrime p)).mp + (h.is_dvr_at_nonzero_prime p hp0 hpm.isPrime) + inferInstance + +/-- If an integral domain is Noetherian, and the localization at every nonzero prime is +a discrete valuation ring, then it is a Dedekind domain. -/ +instance IsDedekindDomainDvr.isDedekindDomain [IsDedekindDomainDvr A] : IsDedekindDomain A where From 3846483877efb7f46a105ba1d340acb55d4b6fca Mon Sep 17 00:00:00 2001 From: Matthew Robert Ballard Date: Tue, 24 Sep 2024 20:52:48 +0000 Subject: [PATCH 135/170] chore (PrimeSpectrum): `RingHom.primeComap` and API (#15114) We break out the function `PrimeSpectrum.comap.toFun` into `RingHom.primeComap` and copy the API for `PrimeSpectrum.comap` independent of the Zariski topology into `RingTheory.PrimeSpectrum` for `primeComap`. We then feed that API back into the proofs for `comap` directly. Co-authored-by: FMLJohn <417963616@qq.com> --- .../PrimeSpectrum/Basic.lean | 66 +++-------- Mathlib/RingTheory/PrimeSpectrum.lean | 110 ++++++++++++++++++ 2 files changed, 124 insertions(+), 52 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index 34df4b8d2c4b9..766ddec99f38a 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -207,21 +207,14 @@ section Comap variable {S' : Type*} [CommSemiring S'] -theorem preimage_comap_zeroLocus_aux (f : R →+* S) (s : Set R) : - (fun y => ⟨Ideal.comap f y.asIdeal, inferInstance⟩ : PrimeSpectrum S → PrimeSpectrum R) ⁻¹' - zeroLocus s = - zeroLocus (f '' s) := by - ext x - simp only [mem_zeroLocus, Set.image_subset_iff, Set.mem_preimage, mem_zeroLocus, Ideal.coe_comap] - -/-- The function between prime spectra of commutative (semi)rings induced by a ring homomorphism. -This function is continuous. -/ +/-- The continuous function between prime spectra of commutative (semi)rings induced by a ring +homomorphism. -/ def comap (f : R →+* S) : C(PrimeSpectrum S, PrimeSpectrum R) where - toFun y := ⟨Ideal.comap f y.asIdeal, inferInstance⟩ + toFun := f.specComap continuous_toFun := by simp only [continuous_iff_isClosed, isClosed_iff_zeroLocus] rintro _ ⟨s, rfl⟩ - exact ⟨_, preimage_comap_zeroLocus_aux f s⟩ + exact ⟨_, preimage_specComap_zeroLocus_aux f s⟩ variable (f : R →+* S) @@ -244,12 +237,10 @@ theorem comap_comp_apply (f : R →+* S) (g : S →+* S') (x : PrimeSpectrum S') @[simp] theorem preimage_comap_zeroLocus (s : Set R) : comap f ⁻¹' zeroLocus s = zeroLocus (f '' s) := - preimage_comap_zeroLocus_aux f s + preimage_specComap_zeroLocus_aux f s theorem comap_injective_of_surjective (f : R →+* S) (hf : Function.Surjective f) : - Function.Injective (comap f) := fun x y h => - PrimeSpectrum.ext (Ideal.comap_injective_of_surjective f hf - (congr_arg PrimeSpectrum.asIdeal h : (comap f x).asIdeal = (comap f y).asIdeal)) + Function.Injective (comap f) := fun _ _ h => specComap_injective_of_surjective _ hf h variable (S) @@ -266,29 +257,16 @@ theorem localization_comap_inducing [Algebra R S] (M : Submonoid R) [IsLocalizat exact ⟨_, rfl⟩ theorem localization_comap_injective [Algebra R S] (M : Submonoid R) [IsLocalization M S] : - Function.Injective (comap (algebraMap R S)) := by - intro p q h - replace h := congr_arg (fun x : PrimeSpectrum R => Ideal.map (algebraMap R S) x.asIdeal) h - dsimp only [comap, ContinuousMap.coe_mk] at h - rw [IsLocalization.map_comap M S, IsLocalization.map_comap M S] at h - ext1 - exact h + Function.Injective (comap (algebraMap R S)) := + fun _ _ h => localization_specComap_injective S M h theorem localization_comap_embedding [Algebra R S] (M : Submonoid R) [IsLocalization M S] : Embedding (comap (algebraMap R S)) := ⟨localization_comap_inducing S M, localization_comap_injective S M⟩ theorem localization_comap_range [Algebra R S] (M : Submonoid R) [IsLocalization M S] : - Set.range (comap (algebraMap R S)) = { p | Disjoint (M : Set R) p.asIdeal } := by - ext x - constructor - · simp_rw [disjoint_iff_inf_le] - rintro ⟨p, rfl⟩ x ⟨hx₁, hx₂⟩ - exact (p.2.1 : ¬_) (p.asIdeal.eq_top_of_isUnit_mem hx₂ (IsLocalization.map_units S ⟨x, hx₁⟩)) - · intro h - use ⟨x.asIdeal.map (algebraMap R S), IsLocalization.isPrime_of_isPrime_disjoint M S _ x.2 h⟩ - ext1 - exact IsLocalization.comap_map_of_isPrime_disjoint M S _ x.2 h + Set.range (comap (algebraMap R S)) = { p | Disjoint (M : Set R) p.asIdeal } := + localization_specComap_range .. open Function RingHom @@ -336,28 +314,12 @@ theorem comap_singleton_isClosed_of_isIntegral (f : R →+* S) (hf : f.IsIntegra (Ideal.isMaximal_comap_of_isIntegral_of_isMaximal' f hf x.asIdeal) theorem image_comap_zeroLocus_eq_zeroLocus_comap (hf : Surjective f) (I : Ideal S) : - comap f '' zeroLocus I = zeroLocus (I.comap f) := by - simp only [Set.ext_iff, Set.mem_image, mem_zeroLocus, SetLike.coe_subset_coe] - refine fun p => ⟨?_, fun h_I_p => ?_⟩ - · rintro ⟨p, hp, rfl⟩ a ha - exact hp ha - · have hp : ker f ≤ p.asIdeal := (Ideal.comap_mono bot_le).trans h_I_p - refine ⟨⟨p.asIdeal.map f, Ideal.map_isPrime_of_surjective hf hp⟩, fun x hx => ?_, ?_⟩ - · obtain ⟨x', rfl⟩ := hf x - exact Ideal.mem_map_of_mem f (h_I_p hx) - · ext x - rw [comap_asIdeal, Ideal.mem_comap, Ideal.mem_map_iff_of_surjective f hf] - refine ⟨?_, fun hx => ⟨x, hx, rfl⟩⟩ - rintro ⟨x', hx', heq⟩ - rw [← sub_sub_cancel x' x] - refine p.asIdeal.sub_mem hx' (hp ?_) - rwa [mem_ker, map_sub, sub_eq_zero] + comap f '' zeroLocus I = zeroLocus (I.comap f) := + image_specComap_zeroLocus_eq_zeroLocus_comap _ f hf I theorem range_comap_of_surjective (hf : Surjective f) : - Set.range (comap f) = zeroLocus (ker f) := by - rw [← Set.image_univ] - convert image_comap_zeroLocus_eq_zeroLocus_comap _ _ hf _ - rw [zeroLocus_bot] + Set.range (comap f) = zeroLocus (ker f) := + range_specComap_of_surjective _ f hf theorem isClosed_range_comap_of_surjective (hf : Surjective f) : IsClosed (Set.range (comap f)) := by diff --git a/Mathlib/RingTheory/PrimeSpectrum.lean b/Mathlib/RingTheory/PrimeSpectrum.lean index 07320e17cdf81..e97719ff6ca9f 100644 --- a/Mathlib/RingTheory/PrimeSpectrum.lean +++ b/Mathlib/RingTheory/PrimeSpectrum.lean @@ -5,6 +5,7 @@ Authors: Johan Commelin, Filippo A. E. Nuccio, Andrew Yang -/ import Mathlib.LinearAlgebra.Finsupp import Mathlib.RingTheory.Ideal.Prod +import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.Nilpotent.Lemmas import Mathlib.RingTheory.Noetherian @@ -480,3 +481,112 @@ end Noetherian end CommSemiRing end PrimeSpectrum + +open PrimeSpectrum + +/-- The pullback of an element of `PrimeSpectrum S` along a ring homomorphism `f : R →+* S`. +The bundled continuous version is `PrimeSpectrum.comap`. -/ +abbrev RingHom.specComap {R S : Type*} [CommSemiring R] [CommSemiring S] (f : R →+* S) : + PrimeSpectrum S → PrimeSpectrum R := + fun y => ⟨Ideal.comap f y.asIdeal, inferInstance⟩ + +namespace PrimeSpectrum + +open RingHom + +variable {R S} {S' : Type*} [CommSemiring R] [CommSemiring S] [CommSemiring S'] + +theorem preimage_specComap_zeroLocus_aux (f : R →+* S) (s : Set R) : + f.specComap ⁻¹' zeroLocus s = zeroLocus (f '' s) := by + ext x + simp only [mem_zeroLocus, Set.image_subset_iff, Set.mem_preimage, mem_zeroLocus, Ideal.coe_comap] + +variable (f : R →+* S) + +@[simp] +theorem specComap_asIdeal (y : PrimeSpectrum S) : + (f.specComap y).asIdeal = Ideal.comap f y.asIdeal := + rfl + +@[simp] +theorem specComap_id : (RingHom.id R).specComap = fun x => x := + rfl + +@[simp] +theorem specComap_comp (f : R →+* S) (g : S →+* S') : + (g.comp f).specComap = f.specComap.comp g.specComap := + rfl + +theorem specComap_comp_apply (f : R →+* S) (g : S →+* S') (x : PrimeSpectrum S') : + (g.comp f).specComap x = f.specComap (g.specComap x) := + rfl + +@[simp] +theorem preimage_specComap_zeroLocus (s : Set R) : + f.specComap ⁻¹' zeroLocus s = zeroLocus (f '' s) := + preimage_specComap_zeroLocus_aux f s + +theorem specComap_injective_of_surjective (f : R →+* S) (hf : Function.Surjective f) : + Function.Injective f.specComap := fun x y h => + PrimeSpectrum.ext + (Ideal.comap_injective_of_surjective f hf + (congr_arg PrimeSpectrum.asIdeal h : (f.specComap x).asIdeal = (f.specComap y).asIdeal)) + +variable (S) + +theorem localization_specComap_injective [Algebra R S] (M : Submonoid R) [IsLocalization M S] : + Function.Injective (algebraMap R S).specComap := by + intro p q h + replace h := _root_.congr_arg (fun x : PrimeSpectrum R => Ideal.map (algebraMap R S) x.asIdeal) h + dsimp only [specComap] at h + rw [IsLocalization.map_comap M S, IsLocalization.map_comap M S] at h + ext1 + exact h + +theorem localization_specComap_range [Algebra R S] (M : Submonoid R) [IsLocalization M S] : + Set.range (algebraMap R S).specComap = { p | Disjoint (M : Set R) p.asIdeal } := by + ext x + constructor + · simp_rw [disjoint_iff_inf_le] + rintro ⟨p, rfl⟩ x ⟨hx₁, hx₂⟩ + exact (p.2.1 : ¬_) (p.asIdeal.eq_top_of_isUnit_mem hx₂ (IsLocalization.map_units S ⟨x, hx₁⟩)) + · intro h + use ⟨x.asIdeal.map (algebraMap R S), IsLocalization.isPrime_of_isPrime_disjoint M S _ x.2 h⟩ + ext1 + exact IsLocalization.comap_map_of_isPrime_disjoint M S _ x.2 h + +end PrimeSpectrum + +section SpecOfSurjective + +open Function RingHom + +variable [CommRing R] [CommRing S] +variable (f : R →+* S) +variable {R} + +theorem image_specComap_zeroLocus_eq_zeroLocus_comap (hf : Surjective f) (I : Ideal S) : + f.specComap '' zeroLocus I = zeroLocus (I.comap f) := by + simp only [Set.ext_iff, Set.mem_image, mem_zeroLocus, SetLike.coe_subset_coe] + refine fun p => ⟨?_, fun h_I_p => ?_⟩ + · rintro ⟨p, hp, rfl⟩ a ha + exact hp ha + · have hp : ker f ≤ p.asIdeal := (Ideal.comap_mono bot_le).trans h_I_p + refine ⟨⟨p.asIdeal.map f, Ideal.map_isPrime_of_surjective hf hp⟩, fun x hx => ?_, ?_⟩ + · obtain ⟨x', rfl⟩ := hf x + exact Ideal.mem_map_of_mem f (h_I_p hx) + · ext x + rw [specComap_asIdeal, Ideal.mem_comap, Ideal.mem_map_iff_of_surjective f hf] + refine ⟨?_, fun hx => ⟨x, hx, rfl⟩⟩ + rintro ⟨x', hx', heq⟩ + rw [← sub_sub_cancel x' x] + refine p.asIdeal.sub_mem hx' (hp ?_) + rwa [mem_ker, map_sub, sub_eq_zero] + +theorem range_specComap_of_surjective (hf : Surjective f) : + Set.range f.specComap = zeroLocus (ker f) := by + rw [← Set.image_univ] + convert image_specComap_zeroLocus_eq_zeroLocus_comap _ _ hf _ + rw [zeroLocus_bot] + +end SpecOfSurjective From 9c5f43190beca396e21a967800dd977750acbb78 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 24 Sep 2024 21:10:20 +0000 Subject: [PATCH 136/170] feat(NumberTheory): add converse of Lucas test for primes (#16834) Add the converse of the existing `lucas_primality` theorem, and combine them into a `lucas_primality_iff` theorem Coauthored by @vihdzp --- Mathlib/NumberTheory/LucasPrimality.lean | 28 +++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Mathlib/NumberTheory/LucasPrimality.lean b/Mathlib/NumberTheory/LucasPrimality.lean index ac590aca60046..07fb4a430c5bb 100644 --- a/Mathlib/NumberTheory/LucasPrimality.lean +++ b/Mathlib/NumberTheory/LucasPrimality.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Fintype.Basic import Mathlib.GroupTheory.OrderOfElement import Mathlib.Tactic.Zify import Mathlib.Data.Nat.Totient +import Mathlib.RingTheory.IntegralDomain /-! # The Lucas test for primes. @@ -18,9 +19,6 @@ and `a^d ≠ 1 (mod n)` for any divisor `d | n - 1`. This test is the basis of t certificate. ## TODO - -- Bonus: Show the reverse implication i.e. if a number is prime then it has a Lucas witness. - Use `Units.IsCyclic` from `RingTheory/IntegralDomain` to show the group is cyclic. - Write a tactic that uses this theorem to generate Pratt primality certificates - Integrate Pratt primality certificates into the norm_num primality verifier @@ -59,3 +57,27 @@ theorem lucas_primality (p : ℕ) (a : ZMod p) (ha : a ^ (p - 1) = 1) p - 1 = orderOf a := order_of_a.symm _ = orderOf a' := (orderOf_injective (Units.coeHom (ZMod p)) Units.ext a') _ ≤ Fintype.card (ZMod p)ˣ := orderOf_le_card_univ + +/-- If `p` is prime, then there exists an `a` such that `a^(p-1) = 1 mod p` +and `a^((p-1)/q) ≠ 1 mod p` for all prime factors `q` of `p-1`. +The multiplicative group mod `p` is cyclic, so `a` can be any generator of the group +(which must have order `p-1`). +-/ +theorem reverse_lucas_primality (p : ℕ) (hP : p.Prime) : + ∃ a : ZMod p, a ^ (p - 1) = 1 ∧ ∀ q : ℕ, q.Prime → q ∣ p - 1 → a ^ ((p - 1) / q) ≠ 1 := by + have : Fact p.Prime := ⟨hP⟩ + obtain ⟨g, hg⟩ := IsCyclic.exists_generator (α := (ZMod p)ˣ) + have h1 : orderOf g = p - 1 := by + rwa [orderOf_eq_card_of_forall_mem_zpowers hg, ← Nat.prime_iff_card_units] + have h2 := tsub_pos_iff_lt.2 hP.one_lt + rw [← orderOf_injective (Units.coeHom _) Units.ext _, orderOf_eq_iff h2] at h1 + refine ⟨g, h1.1, fun q hq hqd ↦ ?_⟩ + replace hq := hq.one_lt + exact h1.2 _ (Nat.div_lt_self h2 hq) (Nat.div_pos (Nat.le_of_dvd h2 hqd) (zero_lt_one.trans hq)) + +/-- A number `p` is prime if and only if there exists an `a` such that +`a^(p-1) = 1 mod p` and `a^((p-1)/q) ≠ 1 mod p` for all prime factors `q` of `p-1`. +-/ +theorem lucas_primality_iff (p : ℕ) : p.Prime ↔ + ∃ a : ZMod p, a ^ (p - 1) = 1 ∧ ∀ q : ℕ, q.Prime → q ∣ p - 1 → a ^ ((p - 1) / q) ≠ 1 := + ⟨reverse_lucas_primality p, fun ⟨a, ⟨ha, hb⟩⟩ ↦ lucas_primality p a ha hb⟩ From 652d1bd725d35664690bc81df2b616801e3ac23f Mon Sep 17 00:00:00 2001 From: Matthew Robert Ballard Date: Tue, 24 Sep 2024 21:52:23 +0000 Subject: [PATCH 137/170] chore(Algebra.Lie): do not always coerce a `LieSubmodule` to a `Submodule` to get a type (#16509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We add ```lean instance (priority := high) coeSort : CoeSort (LieSubmodule R L M) (Type w) where coe N := { x : M // x ∈ N } ``` to avoid the coercion to a `Sort` being `{ x : M // x ∈ N.toSubmodule }` and instead be `N` itself. This allows removal of all `adapation_note`s from leanprover/lean4#5020. Ultimately the API here should be expanded and `Coe (LieSubmodule R L M) (Submodule R M)` should be minimized or removed to avoid forcing Lean to unify `LieSubmodule` and `Submodule` unnecessarily. Co-authored-by: Matthew Robert Ballard <100034030+mattrobball@users.noreply.github.com> --- Mathlib/Algebra/Lie/Abelian.lean | 9 +-- Mathlib/Algebra/Lie/CartanExists.lean | 9 +-- Mathlib/Algebra/Lie/Derivation/Killing.lean | 14 ++--- Mathlib/Algebra/Lie/DirectSum.lean | 10 --- Mathlib/Algebra/Lie/EngelSubalgebra.lean | 6 -- Mathlib/Algebra/Lie/IdealOperations.lean | 6 -- Mathlib/Algebra/Lie/Nilpotent.lean | 18 ------ Mathlib/Algebra/Lie/OfAssociative.lean | 5 +- Mathlib/Algebra/Lie/Semisimple/Basic.lean | 22 +++---- Mathlib/Algebra/Lie/Solvable.lean | 12 ++-- Mathlib/Algebra/Lie/Subalgebra.lean | 5 +- Mathlib/Algebra/Lie/Submodule.lean | 69 +++++++++++---------- Mathlib/Algebra/Lie/TensorProduct.lean | 4 +- Mathlib/Algebra/Lie/TraceForm.lean | 13 ++-- Mathlib/Algebra/Lie/Weights/Basic.lean | 18 ++---- Mathlib/Algebra/Lie/Weights/Cartan.lean | 9 +-- Mathlib/Algebra/Lie/Weights/Chain.lean | 13 ++-- Mathlib/Algebra/Lie/Weights/Killing.lean | 6 +- Mathlib/Algebra/Lie/Weights/Linear.lean | 4 +- 19 files changed, 101 insertions(+), 151 deletions(-) diff --git a/Mathlib/Algebra/Lie/Abelian.lean b/Mathlib/Algebra/Lie/Abelian.lean index 9d26a486b09c5..1c88f3135e544 100644 --- a/Mathlib/Algebra/Lie/Abelian.lean +++ b/Mathlib/Algebra/Lie/Abelian.lean @@ -201,20 +201,21 @@ def maxTrivLinearMapEquivLieModuleHom : maxTrivSubmodule R L (M →ₗ[R] N) ≃ @[simp] theorem coe_maxTrivLinearMapEquivLieModuleHom (f : maxTrivSubmodule R L (M →ₗ[R] N)) : - (maxTrivLinearMapEquivLieModuleHom f : M → N) = f := by ext; rfl + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) f : M → N) = f := by ext; rfl @[simp] theorem coe_maxTrivLinearMapEquivLieModuleHom_symm (f : M →ₗ⁅R,L⁆ N) : - (maxTrivLinearMapEquivLieModuleHom.symm f : M → N) = f := + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) |>.symm f : M → N) = f := rfl @[simp] theorem coe_linearMap_maxTrivLinearMapEquivLieModuleHom (f : maxTrivSubmodule R L (M →ₗ[R] N)) : - (maxTrivLinearMapEquivLieModuleHom f : M →ₗ[R] N) = (f : M →ₗ[R] N) := by ext; rfl + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) f : M →ₗ[R] N) = (f : M →ₗ[R] N) := by + ext; rfl @[simp] theorem coe_linearMap_maxTrivLinearMapEquivLieModuleHom_symm (f : M →ₗ⁅R,L⁆ N) : - (maxTrivLinearMapEquivLieModuleHom.symm f : M →ₗ[R] N) = (f : M →ₗ[R] N) := + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) |>.symm f : M →ₗ[R] N) = (f : M →ₗ[R] N) := rfl end LieModule diff --git a/Mathlib/Algebra/Lie/CartanExists.lean b/Mathlib/Algebra/Lie/CartanExists.lean index bbdbc280d8416..ae5ba4fc34d14 100644 --- a/Mathlib/Algebra/Lie/CartanExists.lean +++ b/Mathlib/Algebra/Lie/CartanExists.lean @@ -164,13 +164,6 @@ lemma engel_isBot_of_isMin (hLK : finrank K L ≤ #K) (U : LieSubalgebra K L) -- viewed as endomorphism of `E`. Note that `χ` is polynomial in its argument `r`. -- Similarly: `ψ r` is the characteristic polynomial of `⁅r • u + x, _⁆` -- viewed as endomorphism of `Q`. Note that `ψ` is polynomial in its argument `r`. - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI := E.instLieRingModuleSubtypeMemSubmodule - letI : LieModule K U E := LieSubmodule.instLieModule E let χ : Polynomial (K[X]) := lieCharpoly K E x' u let ψ : Polynomial (K[X]) := lieCharpoly K Q x' u -- It suffices to show that `χ` is the monomial `X ^ r`. @@ -217,7 +210,7 @@ lemma engel_isBot_of_isMin (hLK : finrank K L ≤ #K) (U : LieSubalgebra K L) obtain hz₀|hz₀ := eq_or_ne z 0 · -- If `z = 0`, then `⁅α • u + x, x⁆` vanishes and we use our assumption `x ≠ 0`. refine ⟨⟨x, self_mem_engel K x⟩, ?_, ?_⟩ - · simpa [coe_bracket_of_module, ne_eq, Submodule.mk_eq_zero] using hx₀ + · exact Subtype.coe_ne_coe.mp hx₀ · dsimp only [z] at hz₀ simp only [coe_bracket_of_module, hz₀, LieHom.map_zero, LinearMap.zero_apply] -- If `z ≠ 0`, then `⁅α • u + x, z⁆` vanishes per axiom of Lie algebras diff --git a/Mathlib/Algebra/Lie/Derivation/Killing.lean b/Mathlib/Algebra/Lie/Derivation/Killing.lean index f7aca54a214c2..65e346eb954d5 100644 --- a/Mathlib/Algebra/Lie/Derivation/Killing.lean +++ b/Mathlib/Algebra/Lie/Derivation/Killing.lean @@ -86,16 +86,10 @@ instance instIsKilling_range_ad : LieAlgebra.IsKilling R 𝕀 := /-- The restriction of the Killing form of a finite-dimensional Killing Lie algebra to the range of the adjoint action is nondegenerate. -/ -lemma killingForm_restrict_range_ad_nondegenerate : ((killingForm R 𝔻).restrict 𝕀).Nondegenerate := - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI := LieDerivation.IsKilling.instIsKilling_range_ad R L - letI := LieSubalgebra.lieAlgebra R (LieDerivation R L L) (LieDerivation.ad R L).range - letI := LieSubalgebra.lieRing R (LieDerivation R L L) (LieDerivation.ad R L).range - killingForm_restrict_range_ad R L ▸ LieAlgebra.IsKilling.killingForm_nondegenerate R _ +lemma killingForm_restrict_range_ad_nondegenerate : + ((killingForm R 𝔻).restrict 𝕀).Nondegenerate := by + convert LieAlgebra.IsKilling.killingForm_nondegenerate R 𝕀 + exact killingForm_restrict_range_ad R L /-- The range of the adjoint action on a finite-dimensional Killing Lie algebra is full. -/ @[simp] diff --git a/Mathlib/Algebra/Lie/DirectSum.lean b/Mathlib/Algebra/Lie/DirectSum.lean index f4d73a8802ef0..7d4a6efc56417 100644 --- a/Mathlib/Algebra/Lie/DirectSum.lean +++ b/Mathlib/Algebra/Lie/DirectSum.lean @@ -229,20 +229,10 @@ variable {L : Type w} [LieRing L] [LieAlgebra R L] (I : ι → LieIdeal R L) [this Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/ Typeclass.20resolution.20under.20binders/near/245151099). -/ instance lieRingOfIdeals : LieRing (⨁ i, I i) := - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : (i : ι) → LieRing (I i) := fun _ => LieIdeal.lieRing .. DirectSum.lieRing fun i => ↥(I i) /-- See `DirectSum.lieRingOfIdeals` comment. -/ instance lieAlgebraOfIdeals : LieAlgebra R (⨁ i, I i) := - #adaptation_note /-- After lean4#5020, many instances for Lie algebras and manifolds are no - longer found. -/ - letI : (i : ι) → LieAlgebra R (I i) := fun _ => LieIdeal.lieAlgebra .. - letI : (i : ι) → LieRing (I i) := fun _ => LieIdeal.lieRing .. DirectSum.lieAlgebra fun i => ↥(I i) end Ideals diff --git a/Mathlib/Algebra/Lie/EngelSubalgebra.lean b/Mathlib/Algebra/Lie/EngelSubalgebra.lean index 3a6654de89875..7257a4abad970 100644 --- a/Mathlib/Algebra/Lie/EngelSubalgebra.lean +++ b/Mathlib/Algebra/Lie/EngelSubalgebra.lean @@ -113,12 +113,6 @@ lemma normalizer_eq_self_of_engel_le [IsArtinian R L] rwa [← lie_skew, neg_mem_iff (G := L)] have aux₂ : ∀ n ∈ N, ⁅x, n⁆ ∈ N := fun n hn ↦ le_normalizer H (aux₁ _ hn) let dx : N →ₗ[R] N := (ad R L x).restrict aux₂ - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - have : IsArtinian R { x // x ∈ N } := isArtinian_submodule' _ obtain ⟨k, hk⟩ : ∃ a, ∀ b ≥ a, Codisjoint (LinearMap.ker (dx ^ b)) (LinearMap.range (dx ^ b)) := eventually_atTop.mp <| dx.eventually_codisjoint_ker_pow_range_pow specialize hk (k+1) (Nat.le_add_right k 1) diff --git a/Mathlib/Algebra/Lie/IdealOperations.lean b/Mathlib/Algebra/Lie/IdealOperations.lean index 99a95d581f6e3..0c18a9d49f2d5 100644 --- a/Mathlib/Algebra/Lie/IdealOperations.lean +++ b/Mathlib/Algebra/Lie/IdealOperations.lean @@ -213,12 +213,6 @@ theorem map_bracket_eq [LieModule R L M] : map f ⁅I, N⁆ = ⁅I, map f N⁆ : exact ⟨x, ⟨f n, (mem_map (f n)).mpr ⟨n, hn, rfl⟩⟩, hm⟩ · rintro ⟨x, ⟨m₂, hm₂ : m₂ ∈ map f N⟩, rfl⟩ obtain ⟨n, hn, rfl⟩ := (mem_map m₂).mp hm₂ - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Bracket I M := LieRingModule.toBracket exact ⟨⁅x, n⁆, ⟨x, ⟨n, hn⟩, rfl⟩, by simp⟩ theorem comap_bracket_eq [LieModule R L M] (hf₁ : f.ker = ⊥) (hf₂ : N₂ ≤ f.range) : diff --git a/Mathlib/Algebra/Lie/Nilpotent.lean b/Mathlib/Algebra/Lie/Nilpotent.lean index fd18eb25f5cf4..a215550676406 100644 --- a/Mathlib/Algebra/Lie/Nilpotent.lean +++ b/Mathlib/Algebra/Lie/Nilpotent.lean @@ -412,13 +412,6 @@ lemma disjoint_lowerCentralSeries_maxTrivSubmodule_iff [IsNilpotent R L M] : suffices ¬ Nontrivial (lowerCentralSeriesLast R L M) by exact this (nontrivial_lowerCentralSeriesLast R L M) rw [h.eq_bot, le_bot_iff] at this - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI unique : Unique (⊥ : LieSubmodule R L M) := Submodule.uniqueBot - letI subsing : Subsingleton (⊥ : LieSubmodule R L M) := Unique.instSubsingleton exact this ▸ not_nontrivial _ theorem nontrivial_max_triv_of_isNilpotent [Nontrivial M] [IsNilpotent R L M] : @@ -595,18 +588,7 @@ theorem LieModule.isNilpotent_of_top_iff : Equiv.lieModule_isNilpotent_iff LieSubalgebra.topEquiv (1 : M ≃ₗ[R] M) fun _ _ => rfl @[simp] lemma LieModule.isNilpotent_of_top_iff' : - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : LieRingModule L (⊤ : LieSubmodule R L M) := - LieSubmodule.instLieRingModuleSubtypeMemSubmodule .. IsNilpotent R L {x // x ∈ (⊤ : LieSubmodule R L M)} ↔ IsNilpotent R L M := - letI : LieRingModule L (⊤ : LieSubmodule R L M) := - LieSubmodule.instLieRingModuleSubtypeMemSubmodule .. - letI : LieModule R L {x // x ∈ (⊤ : LieSubmodule R L M)} := - LieSubmodule.instLieModule ⊤ Equiv.lieModule_isNilpotent_iff 1 (LinearEquiv.ofTop ⊤ rfl) fun _ _ ↦ rfl end Morphisms diff --git a/Mathlib/Algebra/Lie/OfAssociative.lean b/Mathlib/Algebra/Lie/OfAssociative.lean index 5b5c5283887a5..10d1f4dcca458 100644 --- a/Mathlib/Algebra/Lie/OfAssociative.lean +++ b/Mathlib/Algebra/Lie/OfAssociative.lean @@ -300,7 +300,10 @@ theorem toEnd_comp_subtype_mem (m : M) (hm : m ∈ (N : Submodule R M)) : @[simp] theorem toEnd_restrict_eq_toEnd (h := N.toEnd_comp_subtype_mem x) : (toEnd R L M x).restrict h = toEnd R L N x := by - ext; simp only [LinearMap.restrict_apply, toEnd_apply_apply, ← coe_bracket] + ext + simp only [LinearMap.restrict_coe_apply, toEnd_apply_apply, ← coe_bracket, + SetLike.coe_eq_coe] + rfl lemma mapsTo_pow_toEnd_sub_algebraMap {φ : R} {k : ℕ} {x : L} : MapsTo ((toEnd R L M x - algebraMap R (Module.End R M) φ) ^ k) N N := by diff --git a/Mathlib/Algebra/Lie/Semisimple/Basic.lean b/Mathlib/Algebra/Lie/Semisimple/Basic.lean index 7768d66b3c772..405111118ee13 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Basic.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Basic.lean @@ -140,11 +140,12 @@ lemma isSimple_of_isAtom (I : LieIdeal R L) (hI : IsAtom I) : IsSimple R I where Submodule.mem_toAddSubmonoid] apply add_mem -- Now `⁅a, y⁆ ∈ J` since `a ∈ I`, `y ∈ J`, and `J` is an ideal of `I`. - · simp only [Submodule.mem_map, LieSubmodule.mem_coeSubmodule, Submodule.coeSubtype, - Subtype.exists, exists_and_right, exists_eq_right, ha, lie_mem_left, exists_true_left] + · simp only [Submodule.mem_map, LieSubmodule.mem_coeSubmodule, Subtype.exists] + erw [Submodule.coeSubtype] + simp only [exists_and_right, exists_eq_right, ha, lie_mem_left, exists_true_left] exact lie_mem_right R I J ⟨a, ha⟩ y hy -- Finally `⁅b, y⁆ = 0`, by the independence of the atoms. - · suffices ⁅b, y.val⁆ = 0 by simp only [this, zero_mem] + · suffices ⁅b, y.val⁆ = 0 by erw [this]; simp only [zero_mem] rw [← LieSubmodule.mem_bot (R := R) (L := L), ← (IsSemisimple.setIndependent_isAtom hI).eq_bot] exact ⟨lie_mem_right R L I b y y.2, lie_mem_left _ _ _ _ _ hb⟩ } @@ -157,7 +158,11 @@ lemma isSimple_of_isAtom (I : LieIdeal R L) (hI : IsAtom I) : IsSimple R I where rw [eq_bot_iff] at this ⊢ intro x hx suffices x ∈ J → x = 0 from this hx - simpa [J'] using @this x.1 + have := @this x.1 + simp only [LieIdeal.incl_coe, LieIdeal.coe_to_lieSubalgebra_to_submodule, + LieSubmodule.mem_mk_iff', Submodule.mem_map, LieSubmodule.mem_coeSubmodule, Subtype.exists, + LieSubmodule.mem_bot, ZeroMemClass.coe_eq_zero, forall_exists_index, and_imp, J'] at this + exact fun _ ↦ this (↑x) x.property hx rfl -- We need to show that `J = ⊥`. -- Since `J` is an ideal of `L`, and `I` is an atom, -- it suffices to show that `J < I`. @@ -276,7 +281,6 @@ instance (priority := 100) instHasTrivialRadical : HasTrivialRadical R L := by intro x y ext simp only [LieIdeal.coe_bracket_of_module, LieSubmodule.coe_bracket, ZeroMemClass.coe_zero] - letI : Bracket I I := LieRingModule.toBracket have : (⁅(⟨x, hJ' x.2⟩ : I), ⟨y, hJ' y.2⟩⁆ : I) = 0 := trivial_lie_zero _ _ _ _ apply_fun Subtype.val at this exact this @@ -302,14 +306,6 @@ theorem subsingleton_of_hasTrivialRadical_lie_abelian [HasTrivialRadical R L] [h theorem abelian_radical_of_hasTrivialRadical [HasTrivialRadical R L] : IsLieAbelian (radical R L) := by - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Unique (⊥ : LieIdeal R L) := Submodule.uniqueBot - letI : Subsingleton (⊥ : LieIdeal R L) := Unique.instSubsingleton - letI : LieModule.IsTrivial L (⊥ : LieIdeal R L) := LieModule.instIsTrivialOfSubsingleton' .. rw [HasTrivialRadical.radical_eq_bot]; exact LieIdeal.isLieAbelian_of_trivial .. /-- The two properties shown to be equivalent here are possible definitions for a Lie algebra diff --git a/Mathlib/Algebra/Lie/Solvable.lean b/Mathlib/Algebra/Lie/Solvable.lean index 8633e9ede390b..f51e86e77306c 100644 --- a/Mathlib/Algebra/Lie/Solvable.lean +++ b/Mathlib/Algebra/Lie/Solvable.lean @@ -287,12 +287,9 @@ instance [IsSolvable R L] : IsSolvable R (⊤ : LieSubalgebra R L) := by @[simp] lemma radical_eq_top_of_isSolvable [IsSolvable R L] : radical R L = ⊤ := by - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - rw [eq_top_iff]; exact le_sSup <| LieAlgebra.instIsSolvableSubtypeMemLieSubalgebraTop R L + rw [eq_top_iff] + have h : IsSolvable R (⊤ : LieSubalgebra R L) := inferInstance + exact le_sSup h /-- Given a solvable Lie ideal `I` with derived series `I = D₀ ≥ D₁ ≥ ⋯ ≥ Dₖ = ⊥`, this is the natural number `k` (the number of inclusions). @@ -338,6 +335,9 @@ noncomputable def derivedAbelianOfIdeal (I : LieIdeal R L) : LieIdeal R L := | 0 => ⊥ | k + 1 => derivedSeriesOfIdeal R L k I +instance : Unique {x // x ∈ (⊥ : LieIdeal R L)} := + inferInstanceAs <| Unique {x // x ∈ (⊥ : Submodule R L)} + theorem abelian_derivedAbelianOfIdeal (I : LieIdeal R L) : IsLieAbelian (derivedAbelianOfIdeal I) := by dsimp only [derivedAbelianOfIdeal] diff --git a/Mathlib/Algebra/Lie/Subalgebra.lean b/Mathlib/Algebra/Lie/Subalgebra.lean index 37990704ca9da..649208ace2362 100644 --- a/Mathlib/Algebra/Lie/Subalgebra.lean +++ b/Mathlib/Algebra/Lie/Subalgebra.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.Algebra.Lie.Basic -import Mathlib.RingTheory.Noetherian +import Mathlib.RingTheory.Artinian /-! # Lie subalgebras @@ -107,6 +107,9 @@ instance [SMul R₁ R] [Module R₁ L] [IsScalarTower R₁ R L] (L' : LieSubalge instance (L' : LieSubalgebra R L) [IsNoetherian R L] : IsNoetherian R L' := isNoetherian_submodule' _ +instance (L' : LieSubalgebra R L) [IsArtinian R L] : IsArtinian R L' := + isArtinian_submodule' _ + end /-- A Lie subalgebra forms a new Lie algebra. -/ diff --git a/Mathlib/Algebra/Lie/Submodule.lean b/Mathlib/Algebra/Lie/Submodule.lean index 2fcf4d22646c5..1ce9ee98b69dc 100644 --- a/Mathlib/Algebra/Lie/Submodule.lean +++ b/Mathlib/Algebra/Lie/Submodule.lean @@ -72,12 +72,12 @@ instance : Zero (LieSubmodule R L M) := instance : Inhabited (LieSubmodule R L M) := ⟨0⟩ -instance coeSubmodule : CoeOut (LieSubmodule R L M) (Submodule R M) := +instance (priority := high) coeSort : CoeSort (LieSubmodule R L M) (Type w) where + coe N := { x : M // x ∈ N } + +instance (priority := mid) coeSubmodule : CoeOut (LieSubmodule R L M) (Submodule R M) := ⟨toSubmodule⟩ -instance instCanLiftSubmoduleLieSubmodule : CanLift (Submodule R M) (LieSubmodule R L M) (·) - (fun N ↦ ∀ {x : L} {m : M}, m ∈ N → ⁅x, m⁆ ∈ N) where - prf N hN := ⟨⟨N, hN⟩, rfl⟩ @[norm_cast] theorem coe_toSubmodule : ((N : Submodule R M) : Set M) = N := @@ -109,7 +109,7 @@ theorem mem_coe {x : M} : x ∈ (N : Set M) ↔ x ∈ N := protected theorem zero_mem : (0 : M) ∈ N := zero_mem N --- Porting note (#10618): @[simp] can prove this +@[simp] theorem mk_eq_zero {x} (h : x ∈ N) : (⟨x, h⟩ : N) = 0 ↔ x = 0 := Subtype.ext_iff_val @@ -156,17 +156,6 @@ instance : LieRingModule L N where lie_add := by intro x m n; apply SetCoe.ext; apply lie_add leibniz_lie := by intro x y m; apply SetCoe.ext; apply leibniz_lie -instance module' {S : Type*} [Semiring S] [SMul S R] [Module S M] [IsScalarTower S R M] : - Module S N := - N.toSubmodule.module' - -instance : Module R N := - N.toSubmodule.module - -instance {S : Type*} [Semiring S] [SMul S R] [SMul Sᵐᵒᵖ R] [Module S M] [Module Sᵐᵒᵖ M] - [IsScalarTower S R M] [IsScalarTower Sᵐᵒᵖ R M] [IsCentralScalar S M] : IsCentralScalar S N := - N.toSubmodule.isCentralScalar - @[simp, norm_cast] theorem coe_zero : ((0 : N) : M) = (0 : M) := rfl @@ -189,10 +178,19 @@ theorem coe_smul (t : R) (m : N) : (↑(t • m) : M) = t • (m : M) := @[simp, norm_cast] theorem coe_bracket (x : L) (m : N) : - letI : Bracket L N := LieRingModule.toBracket (↑⁅x, m⁆ : M) = ⁅x, ↑m⁆ := rfl +-- Copying instances from `Submodule` for correct discrimination keys +instance [IsNoetherian R M] (N : LieSubmodule R L M) : IsNoetherian R N := + inferInstanceAs <| IsNoetherian R N.toSubmodule + +instance [IsArtinian R M] (N : LieSubmodule R L M) : IsArtinian R N := + inferInstanceAs <| IsArtinian R N.toSubmodule + +instance [NoZeroSMulDivisors R M] : NoZeroSMulDivisors R N := + inferInstanceAs <| NoZeroSMulDivisors R N.toSubmodule + variable [LieAlgebra R L] [LieModule R L M] instance instLieModule : LieModule R L N where @@ -249,7 +247,6 @@ instance LieIdeal.lieRingModule {R L : Type*} [CommRing R] [LieRing L] [LieAlgeb @[simp] theorem LieIdeal.coe_bracket_of_module {R L : Type*} [CommRing R] [LieRing L] [LieAlgebra R L] (I : LieIdeal R L) [LieRingModule L M] (x : I) (m : M) : - letI : Bracket I M := LieRingModule.toBracket ⁅x, m⁆ = ⁅(↑x : L), m⁆ := LieSubalgebra.coe_bracket_of_module (I : LieSubalgebra R L) x m @@ -325,6 +322,9 @@ theorem coeSubmodule_le_coeSubmodule : (N : Submodule R M) ≤ N' ↔ N ≤ N' : instance : Bot (LieSubmodule R L M) := ⟨0⟩ +instance instUniqueBot : Unique (⊥ : LieSubmodule R L M) := + inferInstanceAs <| Unique (⊥ : Submodule R M) + @[simp] theorem bot_coe : ((⊥ : LieSubmodule R L M) : Set M) = {0} := rfl @@ -547,10 +547,11 @@ theorem mem_sup (x : M) : x ∈ N ⊔ N' ↔ ∃ y ∈ N, ∃ z ∈ N', y + z = nonrec theorem eq_bot_iff : N = ⊥ ↔ ∀ m : M, m ∈ N → m = 0 := by rw [eq_bot_iff]; exact Iff.rfl -instance subsingleton_of_bot : Subsingleton (LieSubmodule R L ↑(⊥ : LieSubmodule R L M)) := by +instance subsingleton_of_bot : Subsingleton (LieSubmodule R L (⊥ : LieSubmodule R L M)) := by apply subsingleton_of_bot_eq_top - ext ⟨x, hx⟩; change x ∈ ⊥ at hx; rw [Submodule.mem_bot] at hx; subst hx - simp only [eq_self_iff_true, Submodule.mk_eq_zero, LieSubmodule.mem_bot, mem_top] + ext ⟨_, hx⟩ + simp only [mem_bot, mk_eq_zero, mem_top, iff_true] + exact hx instance : IsModularLattice (LieSubmodule R L M) where sup_inf_le_assoc_of_le _ _ := by @@ -830,9 +831,9 @@ theorem comap_incl_eq_top : N₂.comap N.incl = ⊤ ↔ N ≤ N₂ := by LieSubmodule.top_coeSubmodule, Submodule.comap_subtype_eq_top, coeSubmodule_le_coeSubmodule] theorem comap_incl_eq_bot : N₂.comap N.incl = ⊥ ↔ N ⊓ N₂ = ⊥ := by - simp only [← LieSubmodule.coe_toSubmodule_eq_iff, LieSubmodule.coeSubmodule_comap, - LieSubmodule.incl_coe, LieSubmodule.bot_coeSubmodule, ← Submodule.disjoint_iff_comap_eq_bot, - disjoint_iff, inf_coe_toSubmodule] + simp only [← coe_toSubmodule_eq_iff, coeSubmodule_comap, incl_coe, bot_coeSubmodule, + inf_coe_toSubmodule] + rw [← Submodule.disjoint_iff_comap_eq_bot, disjoint_iff] @[mono] theorem map_mono (h : N ≤ N₂) : N.map f ≤ N₂.map f := @@ -987,9 +988,9 @@ same as ideals of `L` contained in `I`. -/ instance subsingleton_of_bot : Subsingleton (LieIdeal R (⊥ : LieIdeal R L)) := by apply subsingleton_of_bot_eq_top ext ⟨x, hx⟩ - rw [LieSubmodule.bot_coeSubmodule, Submodule.mem_bot] at hx + rw [LieSubmodule.mem_bot] at hx subst hx - simp only [Submodule.mk_eq_zero, LieSubmodule.mem_bot, LieSubmodule.mem_top] + simp only [LieSubmodule.mk_eq_zero, LieSubmodule.mem_bot, LieSubmodule.mem_top] end LieIdeal @@ -1274,11 +1275,11 @@ def range : LieSubmodule R L N := (LieSubmodule.map f ⊤).copy (Set.range f) Set.image_univ.symm @[simp] -theorem coe_range : (f.range : Set N) = Set.range f := +theorem coe_range : f.range = Set.range f := rfl @[simp] -theorem coeSubmodule_range : (f.range : Submodule R N) = LinearMap.range (f : M →ₗ[R] N) := +theorem coeSubmodule_range : f.range = LinearMap.range (f : M →ₗ[R] N) := rfl @[simp] @@ -1297,7 +1298,7 @@ def codRestrict (P : LieSubmodule R L N) (f : M →ₗ⁅R,L⁆ N) (h : ∀ m, f M →ₗ⁅R,L⁆ P where toFun := f.toLinearMap.codRestrict P h __ := f.toLinearMap.codRestrict P h - map_lie' {x m} := by ext; simp; rfl + map_lie' {x m} := by ext; simp @[simp] lemma codRestrict_apply (P : LieSubmodule R L N) (f : M →ₗ⁅R,L⁆ N) (h : ∀ m, f m ∈ P) (m : M) : @@ -1314,13 +1315,17 @@ variable [AddCommGroup M] [Module R M] [LieRingModule L M] variable (N : LieSubmodule R L M) @[simp] -theorem ker_incl : N.incl.ker = ⊥ := by simp [← LieSubmodule.coe_toSubmodule_eq_iff] +theorem ker_incl : N.incl.ker = ⊥ := (LieModuleHom.ker_eq_bot N.incl).mpr <| injective_incl N @[simp] -theorem range_incl : N.incl.range = N := by simp [← LieSubmodule.coe_toSubmodule_eq_iff] +theorem range_incl : N.incl.range = N := by + simp only [← coe_toSubmodule_eq_iff, LieModuleHom.coeSubmodule_range, incl_coe] + rw [Submodule.range_subtype] @[simp] -theorem comap_incl_self : comap N.incl N = ⊤ := by simp [← LieSubmodule.coe_toSubmodule_eq_iff] +theorem comap_incl_self : comap N.incl N = ⊤ := by + simp only [← coe_toSubmodule_eq_iff, coeSubmodule_comap, incl_coe, top_coeSubmodule] + rw [Submodule.comap_subtype_self] theorem map_incl_top : (⊤ : LieSubmodule R L N).map N.incl = N := by simp diff --git a/Mathlib/Algebra/Lie/TensorProduct.lean b/Mathlib/Algebra/Lie/TensorProduct.lean index c44b1b7b2474c..0fe6b3f7fb9e8 100644 --- a/Mathlib/Algebra/Lie/TensorProduct.lean +++ b/Mathlib/Algebra/Lie/TensorProduct.lean @@ -201,8 +201,8 @@ theorem lieIdeal_oper_eq_tensor_map_range : TensorProduct.map_range_eq_span_tmul, Submodule.map_span] congr; ext m; constructor · rintro ⟨⟨x, hx⟩, ⟨n, hn⟩, rfl⟩; use x ⊗ₜ n; constructor - · use ⟨x, hx⟩, ⟨n, hn⟩; simp + · use ⟨x, hx⟩, ⟨n, hn⟩; rfl · simp - · rintro ⟨t, ⟨⟨x, hx⟩, ⟨n, hn⟩, rfl⟩, h⟩; rw [← h]; use ⟨x, hx⟩, ⟨n, hn⟩; simp + · rintro ⟨t, ⟨⟨x, hx⟩, ⟨n, hn⟩, rfl⟩, h⟩; rw [← h]; use ⟨x, hx⟩, ⟨n, hn⟩; rfl end LieSubmodule diff --git a/Mathlib/Algebra/Lie/TraceForm.lean b/Mathlib/Algebra/Lie/TraceForm.lean index 06be6aac63a94..b7b439cf4ddfd 100644 --- a/Mathlib/Algebra/Lie/TraceForm.lean +++ b/Mathlib/Algebra/Lie/TraceForm.lean @@ -302,7 +302,10 @@ variable [IsDomain R] [IsPrincipalIdealRing R] lemma trace_eq_trace_restrict_of_le_idealizer (hy' : ∀ m ∈ N, (φ x ∘ₗ φ y) m ∈ N := fun m _ ↦ N.lie_mem (N.mem_idealizer.mp (h hy) m)) : trace R M (φ x ∘ₗ φ y) = trace R N ((φ x ∘ₗ φ y).restrict hy') := by - suffices ∀ m, ⁅x, ⁅y, m⁆⁆ ∈ N by simp [(φ x ∘ₗ φ y).trace_restrict_eq_of_forall_mem _ this] + suffices ∀ m, ⁅x, ⁅y, m⁆⁆ ∈ N by + have : (trace R { x // x ∈ N }) ((φ x ∘ₗ φ y).restrict _) = (trace R M) (φ x ∘ₗ φ y) := + (φ x ∘ₗ φ y).trace_restrict_eq_of_forall_mem _ this + simp [this] exact fun m ↦ N.lie_mem (h hy m) include h in @@ -322,14 +325,8 @@ lemma traceForm_eq_zero_of_isTrivial [LieModule.IsTrivial I N] : let hy' : ∀ m ∈ N, (φ x ∘ₗ φ y) m ∈ N := fun m _ ↦ N.lie_mem (N.mem_idealizer.mp (h hy) m) suffices (φ x ∘ₗ φ y).restrict hy' = 0 by simp [this, N.trace_eq_trace_restrict_of_le_idealizer I h x hy] - ext n + ext (n : N) suffices ⁅y, (n : M)⁆ = 0 by simp [this] - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Bracket I N := LieRingModule.toBracket exact Submodule.coe_eq_zero.mpr (LieModule.IsTrivial.trivial (⟨y, hy⟩ : I) n) end LieSubmodule diff --git a/Mathlib/Algebra/Lie/Weights/Basic.lean b/Mathlib/Algebra/Lie/Weights/Basic.lean index d267162165c92..310b0d062c7aa 100644 --- a/Mathlib/Algebra/Lie/Weights/Basic.lean +++ b/Mathlib/Algebra/Lie/Weights/Basic.lean @@ -219,13 +219,6 @@ instance [Subsingleton M] : IsEmpty (Weight R L M) := ⟨fun h ↦ h.2 (Subsingleton.elim _ _)⟩ instance [Nontrivial (genWeightSpace M (0 : L → R))] : Zero (Weight R L M) := - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Unique (⊥ : LieSubmodule R L M) := Submodule.uniqueBot - letI : Subsingleton (⊥ : LieSubmodule R L M) := Unique.instSubsingleton ⟨0, fun e ↦ not_nontrivial (⊥ : LieSubmodule R L M) (e ▸ ‹_›)⟩ @[simp] @@ -330,7 +323,9 @@ lemma isNilpotent_toEnd_sub_algebraMap [IsNoetherian R M] (χ : L → R) (x : L) obtain ⟨k, hk⟩ := exists_genWeightSpace_le_ker_of_isNoetherian M χ x use k ext ⟨m, hm⟩ - simpa [this, LinearMap.pow_restrict _, LinearMap.restrict_apply] using hk hm + simp only [this, LinearMap.pow_restrict _, LinearMap.zero_apply, ZeroMemClass.coe_zero, + ZeroMemClass.coe_eq_zero] + exact ZeroMemClass.coe_eq_zero.mp (hk hm) /-- A (nilpotent) Lie algebra acts nilpotently on the zero weight space of a Noetherian Lie module. -/ @@ -590,12 +585,7 @@ private lemma isCompl_genWeightSpace_zero_posFittingComp_aux · suffices IsNilpotent R L M by simp [M₀, M₁, isCompl_top_bot] replace h : M₀ = ⊤ := by simpa [M₀, genWeightSpace] rw [← LieModule.isNilpotent_of_top_iff', ← h] - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - exact LieModule.instIsNilpotentSubtypeMemSubmoduleGenWeightSpaceOfNatForallOfIsNoetherian M + infer_instance · set M₀ₓ := genWeightSpaceOf M (0 : R) x set M₁ₓ := posFittingCompOf R M x set M₀ₓ₀ := genWeightSpace M₀ₓ (0 : L → R) diff --git a/Mathlib/Algebra/Lie/Weights/Cartan.lean b/Mathlib/Algebra/Lie/Weights/Cartan.lean index 152536e842483..bdc8524325ed0 100644 --- a/Mathlib/Algebra/Lie/Weights/Cartan.lean +++ b/Mathlib/Algebra/Lie/Weights/Cartan.lean @@ -88,7 +88,7 @@ def rootSpaceWeightSpaceProductAux {χ₁ χ₂ χ₃ : H → R} (hχ : χ₁ + { toFun := fun m => ⟨⁅(x : L), (m : M)⁆, hχ ▸ lie_mem_genWeightSpace_of_mem_genWeightSpace x.property m.property⟩ - map_add' := fun m n => by simp only [Submodule.coe_add, lie_add, AddMemClass.mk_add_mk] + map_add' := fun m n => by simp only [LieSubmodule.coe_add, lie_add, AddMemClass.mk_add_mk] map_smul' := fun t m => by dsimp only conv_lhs => @@ -97,7 +97,7 @@ def rootSpaceWeightSpaceProductAux {χ₁ χ₂ χ₃ : H → R} (hχ : χ₁ + rfl } map_add' x y := by ext m - simp only [Submodule.coe_add, add_lie, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.add_apply, + simp only [LieSubmodule.coe_add, add_lie, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.add_apply, AddMemClass.mk_add_mk] map_smul' t x := by simp only [RingHom.id_apply] @@ -117,7 +117,6 @@ def rootSpaceWeightSpaceProduct (χ₁ χ₂ χ₃ : H → R) (hχ : χ₁ + χ ext m simp only [rootSpaceWeightSpaceProductAux] dsimp - repeat rw [LieSubmodule.coe_bracket] simp only [LieSubalgebra.coe_bracket_of_module, lie_lie] } @[simp] @@ -271,7 +270,9 @@ lemma mem_corootSpace {x : H} : have : x ∈ corootSpace α ↔ (x : L) ∈ LieSubmodule.map H.toLieSubmodule.incl (corootSpace α) := by rw [corootSpace] - simpa using exists_congr fun _ ↦ H.toLieSubmodule.injective_incl.eq_iff.symm + simp only [rootSpaceProduct_def, LieModuleHom.mem_range, LieSubmodule.mem_map, + LieSubmodule.incl_apply, SetLike.coe_eq_coe, exists_eq_right] + rfl simp_rw [this, corootSpace, ← LieModuleHom.map_top, ← LieSubmodule.mem_coeSubmodule, LieSubmodule.coeSubmodule_map, LieSubmodule.top_coeSubmodule, ← TensorProduct.span_tmul_eq_top, LinearMap.map_span, Set.image, Set.mem_setOf_eq, exists_exists_exists_and_eq] diff --git a/Mathlib/Algebra/Lie/Weights/Chain.lean b/Mathlib/Algebra/Lie/Weights/Chain.lean index 4207a1056e76d..bf2671f9c4c4b 100644 --- a/Mathlib/Algebra/Lie/Weights/Chain.lean +++ b/Mathlib/Algebra/Lie/Weights/Chain.lean @@ -212,11 +212,16 @@ lemma exists_forall_mem_corootSpace_smul_add_eq_zero have h₃ : genWeightSpaceChain M α χ p q = ⨆ i ∈ Finset.Ioo p q, N i := by simp_rw [genWeightSpaceChain_def', LieSubmodule.iSup_coe_toSubmodule] rw [← trace_toEnd_genWeightSpaceChain_eq_zero M α χ p q hp hq hx, - ← LieSubmodule.toEnd_restrict_eq_toEnd, - LinearMap.trace_eq_sum_trace_restrict_of_eq_biSup _ h₁ h₂ (genWeightSpaceChain M α χ p q) h₃] + ← LieSubmodule.toEnd_restrict_eq_toEnd] + -- The lines below illustrate the cost of treating `LieSubmodule` as both a + -- `Submodule` and a `LieSubmodule` simultaneously. + erw [LinearMap.trace_eq_sum_trace_restrict_of_eq_biSup _ h₁ h₂ (genWeightSpaceChain M α χ p q) h₃] + simp_rw [LieSubmodule.toEnd_restrict_eq_toEnd] dsimp [N] - simp_rw [LieSubmodule.toEnd_restrict_eq_toEnd, - trace_toEnd_genWeightSpace, Pi.add_apply, Pi.smul_apply, smul_add, ← smul_assoc, + convert_to _ = + ∑ k ∈ Finset.Ioo p q, (LinearMap.trace R { x // x ∈ (genWeightSpace M (k • α + χ)) }) + ((toEnd R { x // x ∈ H } { x // x ∈ genWeightSpace M (k • α + χ) }) x) + simp_rw [trace_toEnd_genWeightSpace, Pi.add_apply, Pi.smul_apply, smul_add, ← smul_assoc, Finset.sum_add_distrib, ← Finset.sum_smul, natCast_zsmul] end IsCartanSubalgebra diff --git a/Mathlib/Algebra/Lie/Weights/Killing.lean b/Mathlib/Algebra/Lie/Weights/Killing.lean index 30db9a4835dcf..a941003c52c63 100644 --- a/Mathlib/Algebra/Lie/Weights/Killing.lean +++ b/Mathlib/Algebra/Lie/Weights/Killing.lean @@ -534,7 +534,9 @@ lemma _root_.IsSl2Triple.h_eq_coroot {α : Weight K H L} (hα : α.IsNonZero) lemma finrank_rootSpace_eq_one (α : Weight K H L) (hα : α.IsNonZero) : finrank K (rootSpace H α) = 1 := by suffices ¬ 1 < finrank K (rootSpace H α) by - have h₀ : finrank K (rootSpace H α) ≠ 0 := by simpa using α.genWeightSpace_ne_bot + have h₀ : finrank K (rootSpace H α) ≠ 0 := by + convert_to finrank K (rootSpace H α).toSubmodule ≠ 0 + simpa using α.genWeightSpace_ne_bot omega intro contra obtain ⟨h, e, f, ht, heα, hfα⟩ := exists_isSl2Triple_of_weight_isNonZero hα @@ -545,7 +547,7 @@ lemma finrank_rootSpace_eq_one (α : Weight K H L) (hα : α.IsNonZero) : have : killingForm K L y f = 0 := by simpa [F, traceForm_comm] using hy simpa [this] using lie_eq_killingForm_smul_of_mem_rootSpace_of_mem_rootSpace_neg hyα hfα have P : ht.symm.HasPrimitiveVectorWith y (-2 : K) := - { ne_zero := by simpa using hy₀ + { ne_zero := by simpa [LieSubmodule.mk_eq_zero] using hy₀ lie_h := by simp only [neg_smul, neg_lie, neg_inj, ht.h_eq_coroot hα heα hfα, ← H.coe_bracket_of_module, lie_eq_smul_of_mem_rootSpace hyα (coroot α), root_apply_coroot hα] diff --git a/Mathlib/Algebra/Lie/Weights/Linear.lean b/Mathlib/Algebra/Lie/Weights/Linear.lean index bc9f294cf35e7..a4da88d28a011 100644 --- a/Mathlib/Algebra/Lie/Weights/Linear.lean +++ b/Mathlib/Algebra/Lie/Weights/Linear.lean @@ -239,9 +239,9 @@ lemma exists_forall_lie_eq_smul [LinearWeights R L M] [IsNoetherian R M] (χ : W (LieSubmodule.nontrivial_iff_ne_bot R L M).mpr χ.genWeightSpace_ne_bot obtain ⟨⟨⟨m, _⟩, hm₁⟩, hm₂⟩ := @exists_ne _ (nontrivial_max_triv_of_isNilpotent R L (shiftedGenWeightSpace R L M χ)) 0 - simp_rw [LieSubmodule.mem_coeSubmodule, mem_maxTrivSubmodule, Subtype.ext_iff, + simp_rw [mem_maxTrivSubmodule, Subtype.ext_iff, ZeroMemClass.coe_zero] at hm₁ - refine ⟨m, by simpa using hm₂, ?_⟩ + refine ⟨m, by simpa [LieSubmodule.mk_eq_zero] using hm₂, ?_⟩ intro x have := hm₁ x rwa [coe_lie_shiftedGenWeightSpace_apply, sub_eq_zero] at this From 9fbb5feadd1664db15491b4279e75169a7f45837 Mon Sep 17 00:00:00 2001 From: grunweg Date: Wed, 25 Sep 2024 00:06:46 +0000 Subject: [PATCH 138/170] chore: remove autoImplicit tech debt metric (#17107) There are two remaining non-test files which use autoImplicit, and both have purposefully been left with it. Thus, this metric has served its purpose, and can be removed from the list. --- scripts/technical-debt-metrics.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index acf261f75f01b..20c4bc55f3a0f 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -52,8 +52,6 @@ printf '%s|%s\n' "$(grep -c 'docBlame' scripts/nolints.json)" "documentation nol # We count the number of large files, making sure to avoid counting the test file `test/Lint.lean`. printf '%s|%s\n' "$(git grep '^set_option linter.style.longFile [0-9]*' Mathlib | wc -l)" "large files" printf '%s|%s\n' "$(git grep "^open .*Classical" | grep -v " in$" -c)" "bare open (scoped) Classical" -# We print the number of files, not the number of matches --- hence, the nested grep. -printf '%s|%s\n' "$(git grep -c 'autoImplicit true' | grep -c -v 'test')" "non-test files with autoImplicit true" deprecatedFiles="$(git ls-files '**/Deprecated/*.lean' | xargs wc -l | sed 's=^ *==')" From 9910ecab6abb2e4e0c0036b7a16fee9a2fffcbb1 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 25 Sep 2024 00:50:38 +0000 Subject: [PATCH 139/170] chore: bump dependencies and adapt to updated namespaces (#17117) --- Mathlib/Tactic/CategoryTheory/Elementwise.lean | 2 +- Mathlib/Tactic/Linter/Lint.lean | 4 ++-- Mathlib/Tactic/Widget/Calc.lean | 2 +- lake-manifest.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Mathlib/Tactic/CategoryTheory/Elementwise.lean b/Mathlib/Tactic/CategoryTheory/Elementwise.lean index 6ed09d82703a2..4a108c00b9927 100644 --- a/Mathlib/Tactic/CategoryTheory/Elementwise.lean +++ b/Mathlib/Tactic/CategoryTheory/Elementwise.lean @@ -93,7 +93,7 @@ def elementwiseExpr (src : Name) (type pf : Expr) (simpSides := true) : -- check that it's not a simp-trivial equality: forallTelescope ty' fun _ ty' => do if let some (_, lhs, rhs) := ty'.eq? then - if ← Std.Tactic.Lint.isSimpEq lhs rhs then + if ← Batteries.Tactic.Lint.isSimpEq lhs rhs then throwError "applying simp to both sides reduces elementwise lemma for {src} \ to the trivial equality {ty'}. \ Either add `nosimp` or remove the `elementwise` attribute." diff --git a/Mathlib/Tactic/Linter/Lint.lean b/Mathlib/Tactic/Linter/Lint.lean index c4fe07059049e..e1345febe9b36 100644 --- a/Mathlib/Tactic/Linter/Lint.lean +++ b/Mathlib/Tactic/Linter/Lint.lean @@ -13,7 +13,7 @@ In this file we define additional linters for mathlib. Perhaps these should be moved to Batteries in the future. -/ -namespace Std.Tactic.Lint +namespace Batteries.Tactic.Lint open Lean Meta /-- @@ -45,7 +45,7 @@ Linter that checks whether a structure should be in Prop. | some _ => return none -- TODO: enforce `YYYY-MM-DD` format | none => return m!"`deprecated` attribute without `since` date" -end Std.Tactic.Lint +end Batteries.Tactic.Lint namespace Mathlib.Linter diff --git a/Mathlib/Tactic/Widget/Calc.lean b/Mathlib/Tactic/Widget/Calc.lean index bbcba1e9996ae..5e39f560b44b2 100644 --- a/Mathlib/Tactic/Widget/Calc.lean +++ b/Mathlib/Tactic/Widget/Calc.lean @@ -17,7 +17,7 @@ new calc steps with holes specified by selected sub-expressions in the goal. -/ section code_action -open Std CodeAction +open Batteries.CodeAction open Lean Server RequestM /-- Code action to create a `calc` tactic from the current goal. -/ diff --git a/lake-manifest.json b/lake-manifest.json index db5f8604eab98..0cedc34894a16 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "35d1cd731ad832c9f1d860c4d8ec1c7c3ab96823", + "rev": "6d5e1c81277e960372c94f19172440e39b3c5980", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 3c4370ef111b658be8140f18818d0567f8929b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20G=2E=20Dorais?= Date: Wed, 25 Sep 2024 02:09:34 +0000 Subject: [PATCH 140/170] fix: do not rely on the definition for List.ofFn (#17118) --- Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean | 4 ++-- Mathlib/Combinatorics/Optimization/ValuedCSP.lean | 4 ++-- Mathlib/Computability/Primrec.lean | 2 +- Mathlib/LinearAlgebra/CrossProduct.lean | 4 ++-- Mathlib/LinearAlgebra/Dimension/RankNullity.lean | 2 +- Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean | 4 ++-- Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean index 1c20ec00d569e..3d4ea8337acc9 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean @@ -115,8 +115,8 @@ lemma comp_fin3 {S : Type v} (f : R → S) (X Y Z : R) : f ∘ ![X, Y, Z] = ![f variable [CommRing R] -lemma smul_fin3 (P : Fin 3 → R) (u : R) : u • P = ![u * P x, u * P y, u * P z] := - List.ofFn_inj.mp rfl +lemma smul_fin3 (P : Fin 3 → R) (u : R) : u • P = ![u * P x, u * P y, u * P z] := by + simp [← List.ofFn_inj] lemma smul_fin3_ext (P : Fin 3 → R) (u : R) : (u • P) x = u * P x ∧ (u • P) y = u * P y ∧ (u • P) z = u * P z := diff --git a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean b/Mathlib/Combinatorics/Optimization/ValuedCSP.lean index eee23c4281a09..5063e0e98009e 100644 --- a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean +++ b/Mathlib/Combinatorics/Optimization/ValuedCSP.lean @@ -134,7 +134,7 @@ lemma Function.HasMaxCutPropertyAt.rows_lt_aux {r : Fin 2 → D} (rin : r ∈ (ω.tt ![![a, b], ![b, a]])) : f ![a, b] < f r := by rw [FractionalOperation.tt, Multiset.mem_map] at rin - rw [show r = ![r 0, r 1] from List.ofFn_inj.mp rfl] + rw [show r = ![r 0, r 1] by simp [← List.ofFn_inj]] apply lt_of_le_of_ne (mcf.right (r 0) (r 1)).left intro equ have asymm : r 0 ≠ r 1 := by @@ -146,7 +146,7 @@ lemma Function.HasMaxCutPropertyAt.rows_lt_aux apply asymm obtain ⟨o, in_omega, rfl⟩ := rin show o (fun j => ![![a, b], ![b, a]] j 0) = o (fun j => ![![a, b], ![b, a]] j 1) - convert symmega ![a, b] ![b, a] (List.Perm.swap b a []) o in_omega using 2 <;> + convert symmega ![a, b] ![b, a] (by simp [List.Perm.swap]) o in_omega using 2 <;> simp [Matrix.const_fin1_eq] lemma Function.HasMaxCutProperty.forbids_commutativeFractionalPolymorphism diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index 967626fac3c92..103424afc40a5 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -1215,7 +1215,7 @@ theorem vector_get {n} : Primrec₂ (@Vector.get α n) := theorem list_ofFn : ∀ {n} {f : Fin n → α → σ}, (∀ i, Primrec (f i)) → Primrec fun a => List.ofFn fun i => f i a - | 0, _, _ => const [] + | 0, _, _ => by simp only [List.ofFn_zero]; exact const [] | n + 1, f, hf => by simpa [List.ofFn_succ] using list_cons.comp (hf 0) (list_ofFn fun i => hf i.succ) diff --git a/Mathlib/LinearAlgebra/CrossProduct.lean b/Mathlib/LinearAlgebra/CrossProduct.lean index b422330a52d9c..8fb6567b4ec21 100644 --- a/Mathlib/LinearAlgebra/CrossProduct.lean +++ b/Mathlib/LinearAlgebra/CrossProduct.lean @@ -154,8 +154,8 @@ lemma crossProduct_ne_zero_iff_linearIndependent {F : Type*} [Field F] {v w : Fi · rw [LinearIndependent.pair_iff' hv, not_forall_not] rintro ⟨a, rfl⟩ rw [LinearMap.map_smul, cross_self, smul_zero] - have hv' : v = ![v 0, v 1, v 2] := List.ofFn_inj.mp rfl - have hw' : w = ![w 0, w 1, w 2] := List.ofFn_inj.mp rfl + have hv' : v = ![v 0, v 1, v 2] := by simp [← List.ofFn_inj] + have hw' : w = ![w 0, w 1, w 2] := by simp [← List.ofFn_inj] intro h1 h2 simp_rw [cross_apply, cons_eq_zero_iff, zero_empty, and_true, sub_eq_zero] at h1 have h20 := LinearIndependent.pair_iff.mp h2 (- w 0) (v 0) diff --git a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean index 79cac4a7d7ba4..1e94b3ea6e179 100644 --- a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean +++ b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean @@ -136,7 +136,7 @@ theorem exists_linearIndependent_pair_of_one_lt_rank [StrongRankCondition R] [NoZeroSMulDivisors R M] (h : 1 < Module.rank R M) {x : M} (hx : x ≠ 0) : ∃ y, LinearIndependent R ![x, y] := by obtain ⟨y, hy⟩ := exists_linearIndependent_snoc_of_lt_rank (linearIndependent_unique ![x] hx) h - have : Fin.snoc ![x] y = ![x, y] := Iff.mp List.ofFn_inj rfl + have : Fin.snoc ![x] y = ![x, y] := by simp [Fin.snoc, ← List.ofFn_inj] rw [this] at hy exact ⟨y, hy⟩ diff --git a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean index 3b3ed5d5dab30..8992078b835ca 100644 --- a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean @@ -299,8 +299,8 @@ theorem ιMulti_apply {n : ℕ} (v : Fin n → M) : ιMulti R n v = (List.ofFn f rfl @[simp] -theorem ιMulti_zero_apply (v : Fin 0 → M) : ιMulti R 0 v = 1 := - rfl +theorem ιMulti_zero_apply (v : Fin 0 → M) : ιMulti R 0 v = 1 := by + simp [ιMulti] @[simp] theorem ιMulti_succ_apply {n : ℕ} (v : Fin n.succ → M) : diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean index 12adf5ad0f2b0..e37eea1ee4fdd 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean @@ -32,8 +32,8 @@ theorem toTensorAlgebra_tprod {n} (x : Fin n → M) : @[simp] theorem toTensorAlgebra_gOne : - TensorPower.toTensorAlgebra (@GradedMonoid.GOne.one _ (fun n => ⨂[R]^n M) _ _) = 1 := - TensorPower.toTensorAlgebra_tprod _ + TensorPower.toTensorAlgebra (@GradedMonoid.GOne.one _ (fun n => ⨂[R]^n M) _ _) = 1 := by + simp [GradedMonoid.GOne.one, TensorPower.toTensorAlgebra_tprod] @[simp] theorem toTensorAlgebra_gMul {i j} (a : (⨂[R]^i) M) (b : (⨂[R]^j) M) : From f7eb186981d26df6a660ad65bc92771d8bcf146b Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Wed, 25 Sep 2024 02:33:10 +0000 Subject: [PATCH 141/170] fix: remove non-breaking-space (#17116) Replace more non-breaking-spaces with regular spaces --- .../Condensed/Discrete/LocallyConstant.lean | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Mathlib/Condensed/Discrete/LocallyConstant.lean b/Mathlib/Condensed/Discrete/LocallyConstant.lean index 384896122a812..56e2cdc31aca0 100644 --- a/Mathlib/Condensed/Discrete/LocallyConstant.lean +++ b/Mathlib/Condensed/Discrete/LocallyConstant.lean @@ -23,10 +23,10 @@ the functor of sheaves of locally constant maps described above. The hard part of this adjunction is to define the counit. Its components are defined as follows: -Let `S : CompHausLike P` and let `Y` be a finite-product preserving presheaf on `CompHausLike P`  +Let `S : CompHausLike P` and let `Y` be a finite-product preserving presheaf on `CompHausLike P` (e.g. a sheaf for the coherent topology). We need to define a map `LocallyConstant S Y(*) ⟶ Y(S)`. Given a locally constant map `f : S → Y(*)`, let `S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding -decomposition of `S` into the fibers. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ` and denote +decomposition of `S` into the fibers. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ` and denote by `gᵢ` the canonical map `Y(*) → Y(Sᵢ)`. Our map then takes `f` to the image of `(g₁(y₁), ⋯, gₙ(yₙ))` under the isomorphism `Y(S₁) × ⋯ × Y(Sₙ) ≅ Y(S₁ ⊔ ⋯ ⊔ Sₙ) = Y(S)`. @@ -34,14 +34,14 @@ Now we need to prove that the counit is natural in `S : CompHausLike P` and `Y : Sheaf (coherentTopology (CompHausLike P)) (Type _)`. There are two key lemmas in all naturality proofs in this file (both lemmas are in the `CompHausLike.LocallyConstant` namespace): -* `presheaf_ext`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, another presheaf +* `presheaf_ext`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, another presheaf `X`, and two elements `x y : X(S)`, to prove that `x = y` it suffices to prove that for every inclusion map `ιᵢ : Sᵢ ⟶ S`, `X(ιᵢ)(x) = X(ιᵢ)(y)`. - Here it is important that we set everything up in such a way that the `Sᵢ` are literally subtypes - of `S`.  + Here it is important that we set everything up in such a way that the `Sᵢ` are literally subtypes + of `S`. -* `incl_of_counitAppApp`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, we have - `Y(ιᵢ)(ε_{S, Y}(f)) = gᵢ(yᵢ)` where `ε` denotes the counit and the other notation is like above. +* `incl_of_counitAppApp`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, we have + `Y(ιᵢ)(ε_{S, Y}(f)) = gᵢ(yᵢ)` where `ε` denotes the counit and the other notation is like above. ## Main definitions @@ -139,8 +139,8 @@ noncomputable def counitAppAppImage : (a : Fiber f) → Y.obj ⟨fiber f a⟩ := /-- The counit is defined as follows: given a locally constant map `f : S → Y(*)`, let -`S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding decomposition of `S` into the fibers. We need to provide an -element of `Y(S)`. It suffices to provide an element of `Y(Sᵢ)` for all `i`. Let `yᵢ ∈ Y(*)` denote +`S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding decomposition of `S` into the fibers. We need to provide an +element of `Y(S)`. It suffices to provide an element of `Y(Sᵢ)` for all `i`. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ`. Our desired element is the image of `yᵢ` under the canonical map `Y(*) → Y(Sᵢ)`. -/ @@ -178,7 +178,7 @@ variable {T : CompHausLike.{u} P} (g : T ⟶ S) /-- This is an auxiliary definition, the details do not matter. What's important is that this map exists -so that the lemma `incl_comap` works. +so that the lemma `incl_comap` works. -/ def componentHom (a : Fiber (f.comap g)) : fiber _ a ⟶ fiber _ (Fiber.mk f (g a.preimage)) where @@ -220,13 +220,13 @@ variable (P) (X : TopCat.{max u w}) [HasExplicitFiniteCoproducts.{0} P] [HasExplicitPullbacks P] (hs : ∀ ⦃X Y : CompHausLike P⦄ (f : X ⟶ Y), EffectiveEpi f → Function.Surjective f) -/-- `locallyConstantIsoContinuousMap` is a natural isomorphism. -/ +/-- `locallyConstantIsoContinuousMap` is a natural isomorphism. -/ noncomputable def functorToPresheavesIsoTopCatToSheafCompHausLike (X : Type (max u w)) : functorToPresheaves.{u, w}.obj X ≅ ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).val := NatIso.ofComponents (fun S ↦ locallyConstantIsoContinuousMap _ _) -/-- `CompHausLike.LocallyConstant.functorToPresheaves` lands in sheaves. -/ +/-- `CompHausLike.LocallyConstant.functorToPresheaves` lands in sheaves. -/ @[simps] def functor : have := CompHausLike.preregular hs @@ -239,7 +239,7 @@ def functor : map f := ⟨functorToPresheaves.{u, w}.map f⟩ /-- -`CompHausLike.LocallyConstant.functor` is naturally isomorphic to the restriction of +`CompHausLike.LocallyConstant.functor` is naturally isomorphic to the restriction of `topCatToSheafCompHausLike` to discrete topological spaces. -/ noncomputable def functorIsoTopCatToSheafCompHausLike : @@ -289,7 +289,7 @@ noncomputable def counit [HasExplicitFiniteCoproducts.{u} P] : haveI := CompHaus exact (mem_iff_eq_image (g.val.app _ ∘ f) _ _).symm /-- -The unit of the adjunciton is given by mapping each element to the corresponding constant map. +The unit of the adjunciton is given by mapping each element to the corresponding constant map. -/ @[simps] def unit : 𝟭 _ ⟶ functor P hs ⋙ (sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩ where @@ -321,7 +321,7 @@ lemma adjunction_left_triangle [HasExplicitFiniteCoproducts.{u} P] rfl /-- -`CompHausLike.LocallyConstant.functor` is left adjoint to the forgetful functor. +`CompHausLike.LocallyConstant.functor` is left adjoint to the forgetful functor. -/ @[simps] noncomputable def adjunction [HasExplicitFiniteCoproducts.{u} P] : @@ -372,7 +372,7 @@ abbrev functor : Type (u+1) ⥤ CondensedSet.{u} := (hs := fun _ _ _ ↦ ((CompHaus.effectiveEpi_tfae _).out 0 2).mp) /-- -`CondensedSet.LocallyConstant.functor` is isomorphic to `Condensed.discrete` +`CondensedSet.LocallyConstant.functor` is isomorphic to `Condensed.discrete` (by uniqueness of adjoints). -/ noncomputable def iso : functor ≅ discrete (Type (u+1)) := @@ -406,7 +406,7 @@ instance (S : LightProfinite.{u}) (p : S → Prop) : (inferInstance : SecondCountableTopology {s | p s})⟩⟩ /-- -`LightCondSet.LocallyConstant.functor` is isomorphic to `LightCondensed.discrete` +`LightCondSet.LocallyConstant.functor` is isomorphic to `LightCondensed.discrete` (by uniqueness of adjoints). -/ noncomputable def iso : functor ≅ LightCondensed.discrete (Type u) := From f8769ab4b2918a996a80723bcdd578628bd93101 Mon Sep 17 00:00:00 2001 From: Lorenzo Luccioli Date: Wed, 25 Sep 2024 08:19:39 +0000 Subject: [PATCH 142/170] feat(MeasureTheory): generalize instance `ContinuousInv.measurableInv` (#17082) Weaken the hypotheses of the instance `ContinuousInv.measurableInv` and change its name (it was called `TopologicalGroup.measurableInv` before). --- Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 4c6af21ff5643..b7ac515ab27d0 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -502,9 +502,8 @@ instance (priority := 100) ContinuousSub.measurableSub [Sub γ] [ContinuousSub measurable_sub_const _ := (continuous_id.sub continuous_const).measurable @[to_additive] -instance (priority := 100) TopologicalGroup.measurableInv [Group γ] [TopologicalGroup γ] : - MeasurableInv γ := - ⟨continuous_inv.measurable⟩ +instance (priority := 100) ContinuousInv.measurableInv [Inv γ] [ContinuousInv γ] : + MeasurableInv γ := ⟨continuous_inv.measurable⟩ @[to_additive] instance (priority := 100) ContinuousSMul.measurableSMul {M α} [TopologicalSpace M] From 1fc8e52be3a70d1447fc79f080750bbd0280aff8 Mon Sep 17 00:00:00 2001 From: Lorenzo Luccioli Date: Wed, 25 Sep 2024 08:40:04 +0000 Subject: [PATCH 143/170] feat (MeasureTheory): Integrability and integral when the domain is empty. (#15459) - Add `Integrable.of_isEmpty`. - Add `integral_of_isEmpty`. --- Mathlib/MeasureTheory/Function/L1Space.lean | 3 +++ Mathlib/MeasureTheory/Integral/Bochner.lean | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 4e6447b519aa1..9fb75e137b6c0 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -442,6 +442,9 @@ theorem Integrable.of_finite [Finite α] [MeasurableSpace α] [MeasurableSinglet (μ : Measure α) [IsFiniteMeasure μ] (f : α → β) : Integrable (fun a ↦ f a) μ := ⟨(StronglyMeasurable.of_finite f).aestronglyMeasurable, .of_finite⟩ +lemma Integrable.of_isEmpty [IsEmpty α] (f : α → β) (μ : Measure α) : + Integrable f μ := Integrable.of_finite μ f + @[deprecated (since := "2024-02-05")] alias integrable_of_fintype := Integrable.of_finite theorem Memℒp.integrable_norm_rpow {f : α → β} {p : ℝ≥0∞} (hf : Memℒp f p μ) (hp_ne_zero : p ≠ 0) diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index 43d62ecfb9b43..1ea3d369e9733 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -1472,6 +1472,9 @@ theorem integral_zero_measure {m : MeasurableSpace α} (f : α → G) : theorem setIntegral_zero_measure (f : α → G) {μ : Measure α} {s : Set α} (hs : μ s = 0) : ∫ x in s, f x ∂μ = 0 := Measure.restrict_eq_zero.mpr hs ▸ integral_zero_measure f +lemma integral_of_isEmpty [IsEmpty α] {f : α → G} : ∫ x, f x ∂μ = 0 := + μ.eq_zero_of_isEmpty ▸ integral_zero_measure _ + theorem integral_finset_sum_measure {ι} {m : MeasurableSpace α} {f : α → G} {μ : ι → Measure α} {s : Finset ι} (hf : ∀ i ∈ s, Integrable f (μ i)) : ∫ a, f a ∂(∑ i ∈ s, μ i) = ∑ i ∈ s, ∫ a, f a ∂μ i := by From 7c93f8663cb1931f808aae5066e978e043557dbd Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Wed, 25 Sep 2024 08:58:26 +0000 Subject: [PATCH 144/170] feat: `match_scalars` and `module` tactics (#16593) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contributes two new tactics `match_scalars` and `module`. Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), the `match_scalars` tactic parses the LHS and RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduces the goal to the respective equalities of the `R`-coefficients of each atom. For example, this produces the goal `⊢ a * 1 + b * 1 = (b + a) * 1`: ```lean example [AddCommMonoid M] [Semiring R] [Module R M] (a b : R) (x : M) : a • x + b • x = (b + a) • x := by match_scalars ``` This produces the two goals `⊢ a * (a * 1) + b * (b * 1) = 1` (from the `x` atom) and `⊢ a * -(b * 1) + b * (a * 1) = 0` (from the `y` atom): ```lean example [AddCommGroup M] [Ring R] [Module R M] (a b : R) (x : M) : a • (a • x - b • y) + (b • a • y + b • b • x) = x := by match_scalars ``` The `module` tactic runs the `match_scalars` tactic and then runs the `ring` tactic on each of the coefficient-wise equalities which are created, failing if this does not resolve them. For example, it solves the following goals: ```lean example [AddCommMonoid M] [CommSemiring R] [Module R M] (a b : R) (x : M) : a • x + b • x = (b + a) • x := by module example [AddCommMonoid M] [Field K] [CharZero K] [Module K M] (x : M) : (2:K)⁻¹ • x + (3:K)⁻¹ • x + (6:K)⁻¹ • x = x := by module example [AddCommGroup M] [CommRing R] [Module R M] (a : R) (v w : M) : (1 + a ^ 2) • (v + w) - a • (a • v - w) = v + (1 + a + a ^ 2) • w := by module ``` The scalar type `R` in these tactics is not pre-determined: instead it starts as `ℕ` (when each atom is initially given a scalar `(1:ℕ)`) and gets bumped up into bigger semirings when such semirings are encountered. However, to permit this, it is assumed that there is a "linear order" on all the semirings which appear in the expression: for any two semirings `R` and `S` which occur, we have either `Algebra R S` or `Algebra S R`). Co-authored-by: Eric Wieser Co-authored-by: Patrick Massot --- Mathlib.lean | 1 + Mathlib/Tactic.lean | 1 + Mathlib/Tactic/Module.lean | 656 ++++++++++++++++++++++++++++++++ Mathlib/Tactic/Ring/RingNF.lean | 2 +- test/module.lean | 308 +++++++++++++++ 5 files changed, 967 insertions(+), 1 deletion(-) create mode 100644 Mathlib/Tactic/Module.lean create mode 100644 test/module.lean diff --git a/Mathlib.lean b/Mathlib.lean index cc970198038fa..df6d075a2c08a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4288,6 +4288,7 @@ import Mathlib.Tactic.Measurability.Init import Mathlib.Tactic.MinImports import Mathlib.Tactic.MkIffOfInductiveProp import Mathlib.Tactic.ModCases +import Mathlib.Tactic.Module import Mathlib.Tactic.Monotonicity import Mathlib.Tactic.Monotonicity.Attr import Mathlib.Tactic.Monotonicity.Basic diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index ce50b9c0db698..153a66d29d73b 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -150,6 +150,7 @@ import Mathlib.Tactic.Measurability.Init import Mathlib.Tactic.MinImports import Mathlib.Tactic.MkIffOfInductiveProp import Mathlib.Tactic.ModCases +import Mathlib.Tactic.Module import Mathlib.Tactic.Monotonicity import Mathlib.Tactic.Monotonicity.Attr import Mathlib.Tactic.Monotonicity.Basic diff --git a/Mathlib/Tactic/Module.lean b/Mathlib/Tactic/Module.lean new file mode 100644 index 0000000000000..3d0d70d2126ca --- /dev/null +++ b/Mathlib/Tactic/Module.lean @@ -0,0 +1,656 @@ +/- +Copyright (c) 2024 Heather Macbeth. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Heather Macbeth +-/ +import Mathlib.Algebra.Algebra.Tower +import Mathlib.Algebra.BigOperators.GroupWithZero.Action +import Mathlib.Tactic.Ring +import Mathlib.Util.AtomM + +/-! # A tactic for normalization over modules + +This file provides the two tactics `match_scalars` and `module`. Given a goal which is an equality +in a type `M` (with `M` an `AddCommMonoid`), the `match_scalars` tactic parses the LHS and RHS of +the goal as linear combinations of `M`-atoms over some semiring `R`, and reduces the goal to +the respective equalities of the `R`-coefficients of each atom. The `module` tactic does this and +then runs the `ring` tactic on each of these coefficient-wise equalities, failing if this does not +resolve them. + +The scalar type `R` is not pre-determined: instead it starts as `ℕ` (when each atom is initially +given a scalar `(1:ℕ)`) and gets bumped up into bigger semirings when such semirings are +encountered. However, to permit this, it is assumed that there is a "linear order" on all the +semirings which appear in the expression: for any two semirings `R` and `S` which occur, we have +either `Algebra R S` or `Algebra S R`). +-/ + +open Lean hiding Module +open Meta Elab Qq Mathlib.Tactic List + +namespace Mathlib.Tactic.Module + +/-! ### Theory of lists of pairs (scalar, vector) + +This section contains the lemmas which are orchestrated by the `match_scalars` and `module` tactics +to prove goals in modules. The basic object which these lemmas concern is `NF R M`, a type synonym +for a list of ordered pairs in `R × M`, where typically `M` is an `R`-module. +-/ + +/-- Basic theoretical "normal form" object of the `match_scalars` and `module` tactics: a type +synonym for a list of ordered pairs in `R × M`, where typically `M` is an `R`-module. This is the +form to which the tactics reduce module expressions. + +(It is not a full "normal form" because the scalars, i.e. `R` components, are not themselves +ring-normalized. But this partial normal form is more convenient for our purposes.) -/ +def NF (R : Type*) (M : Type*) := List (R × M) + +namespace NF +variable {S : Type*} {R : Type*} {M : Type*} + +/-- Augment a `Module.NF R M` object `l`, i.e. a list of pairs in `R × M`, by prepending another +pair `p : R × M`. -/ +@[match_pattern] +def cons (p : R × M) (l : NF R M) : NF R M := p :: l + +@[inherit_doc cons] infixl:100 " ::ᵣ " => cons + +/-- Evaluate a `Module.NF R M` object `l`, i.e. a list of pairs in `R × M`, to an element of `M`, by +forming the "linear combination" it specifies: scalar-multiply each `R` term to the corresponding +`M` term, then add them all up. -/ +def eval [Add M] [Zero M] [SMul R M] (l : NF R M) : M := (l.map (fun (⟨r, x⟩ : R × M) ↦ r • x)).sum + +@[simp] theorem eval_cons [AddMonoid M] [SMul R M] (p : R × M) (l : NF R M) : + (p ::ᵣ l).eval = p.1 • p.2 + l.eval := by + unfold eval cons + rw [List.map_cons] + rw [List.sum_cons] + +theorem atom_eq_eval [AddMonoid M] (x : M) : x = NF.eval [(1, x)] := by simp [eval] + +variable (M) in +theorem zero_eq_eval [AddMonoid M] : (0:M) = NF.eval (R := ℕ) (M := M) [] := rfl + +theorem add_eq_eval₁ [AddMonoid M] [SMul R M] (a₁ : R × M) {a₂ : R × M} {l₁ l₂ l : NF R M} + (h : l₁.eval + (a₂ ::ᵣ l₂).eval = l.eval) : + (a₁ ::ᵣ l₁).eval + (a₂ ::ᵣ l₂).eval = (a₁ ::ᵣ l).eval := by + simp only [eval_cons, ← h, add_assoc] + +theorem add_eq_eval₂ [Semiring R] [AddCommMonoid M] [Module R M] (r₁ r₂ : R) (x : M) + {l₁ l₂ l : NF R M} (h : l₁.eval + l₂.eval = l.eval) : + ((r₁, x) ::ᵣ l₁).eval + ((r₂, x) ::ᵣ l₂).eval = ((r₁ + r₂, x) ::ᵣ l).eval := by + simp only [← h, eval_cons, add_smul, add_assoc] + congr! 1 + simp only [← add_assoc] + congr! 1 + rw [add_comm] + +theorem add_eq_eval₃ [Semiring R] [AddCommMonoid M] [Module R M] {a₁ : R × M} (a₂ : R × M) + {l₁ l₂ l : NF R M} (h : (a₁ ::ᵣ l₁).eval + l₂.eval = l.eval) : + (a₁ ::ᵣ l₁).eval + (a₂ ::ᵣ l₂).eval = (a₂ ::ᵣ l).eval := by + simp only [eval_cons, ← h] + nth_rw 4 [add_comm] + simp only [add_assoc] + congr! 2 + rw [add_comm] + +theorem add_eq_eval {R₁ R₂ : Type*} [AddCommMonoid M] [Semiring R] [Module R M] [Semiring R₁] + [Module R₁ M] [Semiring R₂] [Module R₂ M] {l₁ l₂ l : NF R M} {l₁' : NF R₁ M} {l₂' : NF R₂ M} + {x₁ x₂ : M} (hx₁ : x₁ = l₁'.eval) (hx₂ : x₂ = l₂'.eval) (h₁ : l₁.eval = l₁'.eval) + (h₂ : l₂.eval = l₂'.eval) (h : l₁.eval + l₂.eval = l.eval) : + x₁ + x₂ = l.eval := by + rw [hx₁, hx₂, ← h₁, ← h₂, h] + +theorem sub_eq_eval₁ [SMul R M] [AddGroup M] (a₁ : R × M) {a₂ : R × M} {l₁ l₂ l : NF R M} + (h : l₁.eval - (a₂ ::ᵣ l₂).eval = l.eval) : + (a₁ ::ᵣ l₁).eval - (a₂ ::ᵣ l₂).eval = (a₁ ::ᵣ l).eval := by + simp only [eval_cons, ← h, sub_eq_add_neg, add_assoc] + +theorem sub_eq_eval₂ [Ring R] [AddCommGroup M] [Module R M] (r₁ r₂ : R) (x : M) {l₁ l₂ l : NF R M} + (h : l₁.eval - l₂.eval = l.eval) : + ((r₁, x) ::ᵣ l₁).eval - ((r₂, x) ::ᵣ l₂).eval = ((r₁ - r₂, x) ::ᵣ l).eval := by + simp only [← h, eval_cons, sub_smul, sub_eq_add_neg, neg_add, add_smul, neg_smul, add_assoc] + congr! 1 + simp only [← add_assoc] + congr! 1 + rw [add_comm] + +theorem sub_eq_eval₃ [Ring R] [AddCommGroup M] [Module R M] {a₁ : R × M} (a₂ : R × M) + {l₁ l₂ l : NF R M} (h : (a₁ ::ᵣ l₁).eval - l₂.eval = l.eval) : + (a₁ ::ᵣ l₁).eval - (a₂ ::ᵣ l₂).eval = ((-a₂.1, a₂.2) ::ᵣ l).eval := by + simp only [eval_cons, neg_smul, neg_add, sub_eq_add_neg, ← h, ← add_assoc] + congr! 1 + rw [add_comm, add_assoc] + +theorem sub_eq_eval {R₁ R₂ S₁ S₂ : Type*} [AddCommGroup M] [Ring R] [Module R M] [Semiring R₁] + [Module R₁ M] [Semiring R₂] [Module R₂ M] [Semiring S₁] [Module S₁ M] [Semiring S₂] + [Module S₂ M] {l₁ l₂ l : NF R M} {l₁' : NF R₁ M} {l₂' : NF R₂ M} {l₁'' : NF S₁ M} + {l₂'' : NF S₂ M} {x₁ x₂ : M} (hx₁ : x₁ = l₁''.eval) (hx₂ : x₂ = l₂''.eval) + (h₁' : l₁'.eval = l₁''.eval) (h₂' : l₂'.eval = l₂''.eval) (h₁ : l₁.eval = l₁'.eval) + (h₂ : l₂.eval = l₂'.eval) (h : l₁.eval - l₂.eval = l.eval) : + x₁ - x₂ = l.eval := by + rw [hx₁, hx₂, ← h₁', ← h₂', ← h₁, ← h₂, h] + +instance [Neg R] : Neg (NF R M) where + neg l := l.map fun (a, x) ↦ (-a, x) + +theorem eval_neg [AddCommGroup M] [Ring R] [Module R M] (l : NF R M) : (-l).eval = - l.eval := by + simp only [NF.eval, List.map_map, List.sum_neg, NF.instNeg] + congr + ext p + simp + +theorem zero_sub_eq_eval [AddCommGroup M] [Ring R] [Module R M] (l : NF R M) : + 0 - l.eval = (-l).eval := by + simp [eval_neg] + +theorem neg_eq_eval [AddCommGroup M] [Semiring S] [Module S M] [Ring R] [Module R M] {l : NF R M} + {l₀ : NF S M} (hl : l.eval = l₀.eval) {x : M} (h : x = l₀.eval) : + - x = (-l).eval := by + rw [h, ← hl, eval_neg] + +instance [Mul R] : SMul R (NF R M) where + smul r l := l.map fun (a, x) ↦ (r * a, x) + +@[simp] theorem smul_apply [Mul R] (r : R) (l : NF R M) : r • l = l.map fun (a, x) ↦ (r * a, x) := + rfl + +theorem eval_smul [AddCommMonoid M] [Semiring R] [Module R M] {l : NF R M} {x : M} (h : x = l.eval) + (r : R) : (r • l).eval = r • x := by + unfold NF.eval at h ⊢ + simp only [h, smul_sum, map_map, NF.smul_apply] + congr + ext p + simp [mul_smul] + +theorem smul_eq_eval {R₀ : Type*} [AddCommMonoid M] [Semiring R] [Module R M] [Semiring R₀] + [Module R₀ M] [Semiring S] [Module S M] {l : NF R M} {l₀ : NF R₀ M} {s : S} {r : R} + {x : M} (hx : x = l₀.eval) (hl : l.eval = l₀.eval) (hs : r • x = s • x) : + s • x = (r • l).eval := by + rw [← hs, hx, ← hl, eval_smul] + rfl + +theorem eq_cons_cons [AddMonoid M] [SMul R M] {r₁ r₂ : R} (m : M) {l₁ l₂ : NF R M} (h1 : r₁ = r₂) + (h2 : l₁.eval = l₂.eval) : + ((r₁, m) ::ᵣ l₁).eval = ((r₂, m) ::ᵣ l₂).eval := by + simp only [NF.eval, NF.cons] at * + simp [h1, h2] + +theorem eq_cons_const [AddCommMonoid M] [Semiring R] [Module R M] {r : R} (m : M) {n : M} + {l : NF R M} (h1 : r = 0) (h2 : l.eval = n) : + ((r, m) ::ᵣ l).eval = n := by + simp only [NF.eval, NF.cons] at * + simp [h1, h2] + +theorem eq_const_cons [AddCommMonoid M] [Semiring R] [Module R M] {r : R} (m : M) {n : M} + {l : NF R M} (h1 : 0 = r) (h2 : n = l.eval) : + n = ((r, m) ::ᵣ l).eval := by + simp only [NF.eval, NF.cons] at * + simp [← h1, h2] + +theorem eq_of_eval_eq_eval {R₁ R₂ : Type*} [AddCommMonoid M] [Semiring R] [Module R M] [Semiring R₁] + [Module R₁ M] [Semiring R₂] [Module R₂ M] {l₁ l₂ : NF R M} {l₁' : NF R₁ M} {l₂' : NF R₂ M} + {x₁ x₂ : M} (hx₁ : x₁ = l₁'.eval) (hx₂ : x₂ = l₂'.eval) (h₁ : l₁.eval = l₁'.eval) + (h₂ : l₂.eval = l₂'.eval) (h : l₁.eval = l₂.eval) : + x₁ = x₂ := by + rw [hx₁, hx₂, ← h₁, ← h₂, h] + +variable (R) + +/-- Operate on a `Module.NF S M` object `l`, i.e. a list of pairs in `S × M`, where `S` is some +commutative semiring, by applying to each `S`-component the algebra-map from `S` into a specified +`S`-algebra `R`. -/ +def algebraMap [CommSemiring S] [Semiring R] [Algebra S R] (l : NF S M) : NF R M := + l.map (fun ⟨s, x⟩ ↦ (_root_.algebraMap S R s, x)) + +theorem eval_algebraMap [CommSemiring S] [Semiring R] [Algebra S R] [AddMonoid M] [SMul S M] + [MulAction R M] [IsScalarTower S R M] (l : NF S M) : + (l.algebraMap R).eval = l.eval := by + simp only [NF.eval, algebraMap, map_map] + congr + ext + simp [IsScalarTower.algebraMap_smul] + +end NF + +variable {u v : Level} + +/-! ### Lists of expressions representing scalars and vectors, and operations on such lists -/ + +/-- Basic meta-code "normal form" object of the `match_scalars` and `module` tactics: a type synonym +for a list of ordered triples comprising expressions representing terms of two types `R` and `M` +(where typically `M` is an `R`-module), together with a natural number "index". + +The natural number represents the index of the `M` term in the `AtomM` monad: this is not enforced, +but is sometimes assumed in operations. Thus when items `((a₁, x₁), k)` and `((a₂, x₂), k)` +appear in two different `Module.qNF` objects (i.e. with the same `ℕ`-index `k`), it is expected that +the expressions `x₁` and `x₂` are the same. It is also expected that the items in a `Module.qNF` +list are in strictly increasing order by natural-number index. + +By forgetting the natural number indices, an expression representing a `Mathlib.Tactic.Module.NF` +object can be built from a `Module.qNF` object; this construction is provided as +`Mathlib.Tactic.Module.qNF.toNF`. -/ +abbrev qNF (R : Q(Type u)) (M : Q(Type v)) := List ((Q($R) × Q($M)) × ℕ) + +namespace qNF + +variable {M : Q(Type v)} {R : Q(Type u)} + +/-- Given `l` of type `qNF R M`, i.e. a list of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s and a natural +number), build an `Expr` representing an object of type `NF R M` (i.e. `List (R × M)`) in the +in the obvious way: by forgetting the natural numbers and gluing together the `Expr`s. -/ +def toNF (l : qNF R M) : Q(NF $R $M) := + let l' : List Q($R × $M) := (l.map Prod.fst).map (fun (a, x) ↦ q(($a, $x))) + let qt : List Q($R × $M) → Q(List ($R × $M)) := List.rec q([]) (fun e _ l ↦ q($e ::ᵣ $l)) + qt l' + +/-- Given `l` of type `qNF R₁ M`, i.e. a list of `(Q($R₁) × Q($M)) × ℕ`s (two `Expr`s and a natural +number), apply an expression representing a function with domain `R₁` to each of the `Q($R₁)` +components. -/ +def onScalar {u₁ u₂ : Level} {R₁ : Q(Type u₁)} {R₂ : Q(Type u₂)} (l : qNF R₁ M) (f : Q($R₁ → $R₂)) : + qNF R₂ M := + l.map fun ((a, x), k) ↦ ((q($f $a), x), k) + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), construct another such term `l`, which will have the property that in the +`$R`-module `$M`, the sum of the "linear combinations" represented by `l₁` and `l₂` is the linear +combination represented by `l`. + +The construction assumes, to be valid, that the lists `l₁` and `l₂` are in strictly increasing order +by `ℕ`-component, and that if pairs `(a₁, x₁)` and `(a₂, x₂)` appear in `l₁`, `l₂` respectively with +the same `ℕ`-component `k`, then the expressions `x₁` and `x₂` are equal. + +The construction is as follows: merge the two lists, except that if pairs `(a₁, x₁)` and `(a₂, x₂)` +appear in `l₁`, `l₂` respectively with the same `ℕ`-component `k`, then contribute a term +`(a₁ + a₂, x₁)` to the output list with `ℕ`-component `k`. -/ +def add (iR : Q(Semiring $R)) : qNF R M → qNF R M → qNF R M + | [], l => l + | l, [] => l + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + ((a₁, x₁), k₁) ::ᵣ add iR t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + else if k₁ = k₂ then + ((q($a₁ + $a₂), x₁), k₁) ::ᵣ add iR t₁ t₂ + else + ((a₂, x₂), k₂) ::ᵣ add iR (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), recursively construct a proof that in the `$R`-module `$M`, the sum of the +"linear combinations" represented by `l₁` and `l₂` is the linear combination represented by +`Module.qNF.add iR l₁ l₁`.-/ +def mkAddProof {iR : Q(Semiring $R)} {iM : Q(AddCommMonoid $M)} (iRM : Q(Module $R $M)) + (l₁ l₂ : qNF R M) : + Q(NF.eval $(l₁.toNF) + NF.eval $(l₂.toNF) = NF.eval $((qNF.add iR l₁ l₂).toNF)) := + match l₁, l₂ with + | [], l => (q(zero_add (NF.eval $(l.toNF))):) + | l, [] => (q(add_zero (NF.eval $(l.toNF))):) + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + let pf := mkAddProof iRM t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + (q(NF.add_eq_eval₁ ($a₁, $x₁) $pf):) + else if k₁ = k₂ then + let pf := mkAddProof iRM t₁ t₂ + (q(NF.add_eq_eval₂ $a₁ $a₂ $x₁ $pf):) + else + let pf := mkAddProof iRM (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + (q(NF.add_eq_eval₃ ($a₂, $x₂) $pf):) + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), construct another such term `l`, which will have the property that in the +`$R`-module `$M`, the difference of the "linear combinations" represented by `l₁` and `l₂` is the +linear combination represented by `l`. + +The construction assumes, to be valid, that the lists `l₁` and `l₂` are in strictly increasing order +by `ℕ`-component, and that if pairs `(a₁, x₁)` and `(a₂, x₂)` appear in `l₁`, `l₂` respectively with +the same `ℕ`-component `k`, then the expressions `x₁` and `x₂` are equal. + +The construction is as follows: merge the first list and the negation of the second list, except +that if pairs `(a₁, x₁)` and `(a₂, x₂)` appear in `l₁`, `l₂` respectively with the same +`ℕ`-component `k`, then contribute a term `(a₁ - a₂, x₁)` to the output list with `ℕ`-component `k`. +-/ +def sub (iR : Q(Ring $R)) : qNF R M → qNF R M → qNF R M + | [], l => l.onScalar q(Neg.neg) + | l, [] => l + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + ((a₁, x₁), k₁) ::ᵣ sub iR t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + else if k₁ = k₂ then + ((q($a₁ - $a₂), x₁), k₁) ::ᵣ sub iR t₁ t₂ + else + ((q(-$a₂), x₂), k₂) ::ᵣ sub iR (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), recursively construct a proof that in the `$R`-module `$M`, the difference +of the "linear combinations" represented by `l₁` and `l₂` is the linear combination represented by +`Module.qNF.sub iR l₁ l₁`.-/ +def mkSubProof (iR : Q(Ring $R)) (iM : Q(AddCommGroup $M)) (iRM : Q(Module $R $M)) + (l₁ l₂ : qNF R M) : + Q(NF.eval $(l₁.toNF) - NF.eval $(l₂.toNF) = NF.eval $((qNF.sub iR l₁ l₂).toNF)) := + match l₁, l₂ with + | [], l => (q(NF.zero_sub_eq_eval $(l.toNF)):) + | l, [] => (q(sub_zero (NF.eval $(l.toNF))):) + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + let pf := mkSubProof iR iM iRM t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + (q(NF.sub_eq_eval₁ ($a₁, $x₁) $pf):) + else if k₁ = k₂ then + let pf := mkSubProof iR iM iRM t₁ t₂ + (q(NF.sub_eq_eval₂ $a₁ $a₂ $x₁ $pf):) + else + let pf := mkSubProof iR iM iRM (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + (q(NF.sub_eq_eval₃ ($a₂, $x₂) $pf):) + +variable {iM : Q(AddCommMonoid $M)} + {u₁ : Level} {R₁ : Q(Type u₁)} {iR₁ : Q(Semiring $R₁)} (iRM₁ : Q(@Module $R₁ $M $iR₁ $iM)) + {u₂ : Level} {R₂ : Q(Type u₂)} (iR₂ : Q(Semiring $R₂)) (iRM₂ : Q(@Module $R₂ $M $iR₂ $iM)) + +/-- Given an expression `M` representing a type which is an `AddCommMonoid` and a module over *two* +semirings `R₁` and `R₂`, find the "bigger" of the two semirings. That is, we assume that it will +turn out to be the case that either (1) `R₁` is an `R₂`-algebra and the `R₂` scalar action on `M` is +induced from `R₁`'s scalar action on `M`, or (2) vice versa; we return the semiring `R₁` in the +first case and `R₂` in the second case. + +Moreover, given expressions representing particular scalar multiplications of `R₁` and/or `R₂` on +`M` (a `List (R₁ × M)`, a `List (R₂ × M)`, a pair `(r, x) : R₂ × M`), bump these up to the "big" +ring by applying the algebra-map where needed. -/ +def matchRings (l₁ : qNF R₁ M) (l₂ : qNF R₂ M) (r : Q($R₂)) (x : Q($M)) : + MetaM <| Σ u : Level, Σ R : Q(Type u), Σ iR : Q(Semiring $R), Σ _ : Q(@Module $R $M $iR $iM), + (Σ l₁' : qNF R M, Q(NF.eval $(l₁'.toNF) = NF.eval $(l₁.toNF))) + × (Σ l₂' : qNF R M, Q(NF.eval $(l₂'.toNF) = NF.eval $(l₂.toNF))) + × (Σ r' : Q($R), Q($r' • $x = $r • $x)) := do + if ← withReducible <| isDefEq R₁ R₂ then + -- the case when `R₁ = R₂` is handled separately, so as not to require commutativity of that ring + pure ⟨u₁, R₁, iR₁, iRM₁, ⟨l₁, q(rfl)⟩, ⟨l₂, (q(@rfl _ (NF.eval $(l₂.toNF))):)⟩, + r, (q(@rfl _ ($r • $x)):)⟩ + -- otherwise the "smaller" of the two rings must be commutative + else try + -- first try to exhibit `R₂` as an `R₁`-algebra + let _i₁ ← synthInstanceQ q(CommSemiring $R₁) + let _i₃ ← synthInstanceQ q(Algebra $R₁ $R₂) + let _i₄ ← synthInstanceQ q(IsScalarTower $R₁ $R₂ $M) + assumeInstancesCommute + let l₁' : qNF R₂ M := l₁.onScalar q(algebraMap $R₁ $R₂) + pure ⟨u₂, R₂, iR₂, iRM₂, ⟨l₁', (q(NF.eval_algebraMap $R₂ $(l₁.toNF)):)⟩, ⟨l₂, q(rfl)⟩, + r, q(rfl)⟩ + catch _ => try + -- then if that fails, try to exhibit `R₁` as an `R₂`-algebra + let _i₁ ← synthInstanceQ q(CommSemiring $R₂) + let _i₃ ← synthInstanceQ q(Algebra $R₂ $R₁) + let _i₄ ← synthInstanceQ q(IsScalarTower $R₂ $R₁ $M) + assumeInstancesCommute + let l₂' : qNF R₁ M := l₂.onScalar q(algebraMap $R₂ $R₁) + let r' : Q($R₁) := q(algebraMap $R₂ $R₁ $r) + pure ⟨u₁, R₁, iR₁, iRM₁, ⟨l₁, q(rfl)⟩, ⟨l₂', (q(NF.eval_algebraMap $R₁ $(l₂.toNF)):)⟩, + r', (q(IsScalarTower.algebraMap_smul $R₁ $r $x):)⟩ + catch _ => + throwError "match_scalars failed: {R₁} is not an {R₂}-algebra and {R₂} is not an {R₁}-algebra" + +end qNF + +/-! ### Core of the `module` tactic -/ + +variable {M : Q(Type v)} + +/-- The main algorithm behind the `match_scalars` and `module` tactics: partially-normalizing an +expression in an additive commutative monoid `M` into the form c1 • x1 + c2 • x2 + ... c_k • x_k, +where x1, x2, ... are distinct atoms in `M`, and c1, c2, ... are scalars. The scalar type of the +expression is not pre-determined: instead it starts as `ℕ` (when each atom is initially given a +scalar `(1:ℕ)`) and gets bumped up into bigger semirings when such semirings are encountered. + +It is assumed that there is a "linear order" on all the semirings which appear in the expression: +for any two semirings `R` and `S` which occur, we have either `Algebra R S` or `Algebra S R`). + +TODO: implement a variant in which a semiring `R` is provided by the user, and the assumption is +instead that for any semiring `S` which occurs, we have `Algebra S R`. The PR #16984 provides a +proof-of-concept implementation of this variant, but it would need some polishing before joining +Mathlib. + +Possible TODO, if poor performance on large problems is witnessed: switch the implementation from +`AtomM` to `CanonM`, per the discussion +https://github.com/leanprover-community/mathlib4/pull/16593/files#r1749623191 -/ +partial def parse (iM : Q(AddCommMonoid $M)) (x : Q($M)) : + AtomM (Σ u : Level, Σ R : Q(Type u), Σ iR : Q(Semiring $R), Σ _ : Q(@Module $R $M $iR $iM), + Σ l : qNF R M, Q($x = NF.eval $(l.toNF))) := do + match x with + /- parse an addition: `x₁ + x₂` -/ + | ~q($x₁ + $x₂) => + let ⟨_, _, _, iRM₁, l₁', pf₁'⟩ ← parse iM x₁ + let ⟨_, _, _, iRM₂, l₂', pf₂'⟩ ← parse iM x₂ + -- lift from the semirings of scalars parsed from `x₁`, `x₂` (say `R₁`, `R₂`) to `R₁ ⊗ R₂` + let ⟨u, R, iR, iRM, ⟨l₁, pf₁⟩, ⟨l₂, pf₂⟩, _⟩ ← qNF.matchRings iRM₁ _ iRM₂ l₁' l₂' q(0) q(0) + -- build the new list and proof + let pf := qNF.mkAddProof iRM l₁ l₂ + pure ⟨u, R, iR, iRM, qNF.add iR l₁ l₂, (q(NF.add_eq_eval $pf₁' $pf₂' $pf₁ $pf₂ $pf):)⟩ + /- parse a subtraction: `x₁ - x₂` -/ + | ~q(@HSub.hSub _ _ _ (@instHSub _ $iM') $x₁ $x₂) => + let ⟨_, _, _, iRM₁, l₁'', pf₁''⟩ ← parse iM x₁ + let ⟨_, _, _, iRM₂, l₂'', pf₂''⟩ ← parse iM x₂ + -- lift from the semirings of scalars parsed from `x₁`, `x₂` (say `R₁`, `R₂`) to `R₁ ⊗ R₂ ⊗ ℤ` + let iZ := q(Int.instSemiring) + let iMZ ← synthInstanceQ q(Module ℤ $M) + let ⟨_, _, _, iRM₁', ⟨l₁', pf₁'⟩, _, _⟩ ← qNF.matchRings iRM₁ iZ iMZ l₁'' [] q(0) q(0) + let ⟨_, _, _, iRM₂', ⟨l₂', pf₂'⟩, _, _⟩ ← qNF.matchRings iRM₂ iZ iMZ l₂'' [] q(0) q(0) + let ⟨u, R, iR, iRM, ⟨l₁, pf₁⟩, ⟨l₂, pf₂⟩, _⟩ ← qNF.matchRings iRM₁' _ iRM₂' l₁' l₂' q(0) q(0) + let iR' ← synthInstanceQ q(Ring $R) + let iM' ← synthInstanceQ q(AddCommGroup $M) + assumeInstancesCommute + -- build the new list and proof + let pf := qNF.mkSubProof iR' iM' iRM l₁ l₂ + pure ⟨u, R, iR, iRM, qNF.sub iR' l₁ l₂, + q(NF.sub_eq_eval $pf₁'' $pf₂'' $pf₁' $pf₂' $pf₁ $pf₂ $pf)⟩ + /- parse a negation: `-y` -/ + | ~q(@Neg.neg _ $iM' $y) => + let ⟨u₀, _, _, iRM₀, l₀, pf₀⟩ ← parse iM y + -- lift from original semiring of scalars (say `R₀`) to `R₀ ⊗ ℤ` + let _i ← synthInstanceQ q(AddCommGroup $M) + let iZ := q(Int.instSemiring) + let iMZ ← synthInstanceQ q(Module ℤ $M) + let ⟨u, R, iR, iRM, ⟨l, pf⟩, _, _⟩ ← qNF.matchRings iRM₀ iZ iMZ l₀ [] q(0) q(0) + let _i' ← synthInstanceQ q(Ring $R) + assumeInstancesCommute + -- build the new list and proof + pure ⟨u, R, iR, iRM, l.onScalar q(Neg.neg), (q(NF.neg_eq_eval $pf $pf₀):)⟩ + /- parse a scalar multiplication: `(s₀ : S) • y` -/ + | ~q(@HSMul.hSMul _ _ _ (@instHSMul $S _ $iS) $s₀ $y) => + let ⟨_, _, _, iRM₀, l₀, pf₀⟩ ← parse iM y + let i₁ ← synthInstanceQ q(Semiring $S) + let i₂ ← synthInstanceQ q(Module $S $M) + assumeInstancesCommute + -- lift from original semiring of scalars (say `R₀`) to `R₀ ⊗ S` + let ⟨u, R, iR, iRM, ⟨l, pf_l⟩, _, ⟨s, pf_r⟩⟩ ← qNF.matchRings iRM₀ i₁ i₂ l₀ [] s₀ y + -- build the new list and proof + pure ⟨u, R, iR, iRM, l.onScalar q(HMul.hMul $s), (q(NF.smul_eq_eval $pf₀ $pf_l $pf_r):)⟩ + /- parse a `(0:M)` -/ + | ~q(0) => + pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [], q(NF.zero_eq_eval $M)⟩ + /- anything else should be treated as an atom -/ + | _ => + let k : ℕ ← AtomM.addAtom x + pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [((q(1), x), k)], + q(NF.atom_eq_eval $x)⟩ + +/-- Given expressions `R` and `M` representing types such that `M`'s is a module over `R`'s, and +given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), construct a list of new goals: that the `R`-coefficient of an `M`-atom which +appears in only one list is zero, and that the `R`-coefficients of an `M`-atom which appears in both +lists are equal. Also construct (dependent on these new goals) a proof that the "linear +combinations" represented by `l₁` and `l₂` are equal in `M`. -/ +partial def reduceCoefficientwise {R : Q(Type u)} {_ : Q(AddCommMonoid $M)} {_ : Q(Semiring $R)} + (iRM : Q(Module $R $M)) (l₁ l₂ : qNF R M) : + MetaM (List MVarId × Q(NF.eval $(l₁.toNF) = NF.eval $(l₂.toNF))) := do + match l₁, l₂ with + /- if both empty, return a `rfl` proof that `(0:M) = 0` -/ + | [], [] => + let pf : Q(NF.eval $(l₁.toNF) = NF.eval $(l₁.toNF)) := q(rfl) + pure ([], pf) + /- if one of the lists is empty and the other one is not, recurse down the nonempty one, + forming goals that each of the listed coefficents is equal to zero -/ + | [], ((a, x), _) ::ᵣ L => + let mvar : Q((0:$R) = $a) ← mkFreshExprMVar q((0:$R) = $a) + let (mvars, pf) ← reduceCoefficientwise iRM [] L + pure (mvar.mvarId! :: mvars, (q(NF.eq_const_cons $x $mvar $pf):)) + | ((a, x), _) ::ᵣ L, [] => + let mvar : Q($a = (0:$R)) ← mkFreshExprMVar q($a = (0:$R)) + let (mvars, pf) ← reduceCoefficientwise iRM L [] + pure (mvar.mvarId! :: mvars, (q(NF.eq_cons_const $x $mvar $pf):)) + /- if both lists are nonempty, then deal with the numerically-smallest term in either list, + forming a goal that it is equal to zero (if it appears in only one list) or that its + coefficients in the two lists are the same (if it appears in both lists); then recurse -/ + | ((a₁, x₁), k₁) ::ᵣ L₁, ((a₂, x₂), k₂) ::ᵣ L₂ => + if k₁ < k₂ then + let mvar : Q($a₁ = (0:$R)) ← mkFreshExprMVar q($a₁ = (0:$R)) + let (mvars, pf) ← reduceCoefficientwise iRM L₁ l₂ + pure (mvar.mvarId! :: mvars, (q(NF.eq_cons_const $x₁ $mvar $pf):)) + else if k₁ = k₂ then + let mvar : Q($a₁ = $a₂) ← mkFreshExprMVar q($a₁ = $a₂) + let (mvars, pf) ← reduceCoefficientwise iRM L₁ L₂ + pure (mvar.mvarId! :: mvars, (q(NF.eq_cons_cons $x₁ $mvar $pf):)) + else + let mvar : Q((0:$R) = $a₂) ← mkFreshExprMVar q((0:$R) = $a₂) + let (mvars, pf) ← reduceCoefficientwise iRM l₁ L₂ + pure (mvar.mvarId! :: mvars, (q(NF.eq_const_cons $x₂ $mvar $pf):)) + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduce the goal to +the respective equalities of the `R`-coefficients of each atom. + +This is an auxiliary function which produces slightly awkward goals in `R`; they are later cleaned +up by the function `Mathlib.Tactic.Module.postprocess`. -/ +def matchScalarsAux (g : MVarId) : AtomM (List MVarId) := do + /- Parse the goal as an equality in a type `M` of two expressions `lhs` and `rhs`, with `M` + carrying an `AddCommMonoid` instance. -/ + let eqData ← do + match (← g.getType').eq? with + | some e => pure e + | none => throwError "goal {← g.getType} is not an equality" + let .sort v₀ ← whnf (← inferType eqData.1) | unreachable! + let some v := v₀.dec | unreachable! + let ((M : Q(Type v)), (lhs : Q($M)), (rhs :Q($M))) := eqData + let iM ← synthInstanceQ q(AddCommMonoid.{v} $M) + /- Construct from the `lhs` expression a term `l₁` of type `qNF R₁ M` for some semiring `R₁` -- + that is, a list of `(Q($R₁) × Q($M)) × ℕ`s (two `Expr`s and a natural number) -- together with a + proof that `lhs` is equal to the `R₁`-linear combination in `M` this represents. -/ + let e₁ ← parse iM lhs + have u₁ : Level := e₁.fst + have R₁ : Q(Type u₁) := e₁.snd.fst + have _iR₁ : Q(Semiring.{u₁} $R₁) := e₁.snd.snd.fst + let iRM₁ ← synthInstanceQ q(Module $R₁ $M) + assumeInstancesCommute + have l₁ : qNF R₁ M := e₁.snd.snd.snd.snd.fst + let pf₁ : Q($lhs = NF.eval $(l₁.toNF)) := e₁.snd.snd.snd.snd.snd + /- Do the same for the `rhs` expression, obtaining a term `l₂` of type `qNF R₂ M` for some + semiring `R₂`. -/ + let e₂ ← parse iM rhs + have u₂ : Level := e₂.fst + have R₂ : Q(Type u₂) := e₂.snd.fst + have _iR₂ : Q(Semiring.{u₂} $R₂) := e₂.snd.snd.fst + let iRM₂ ← synthInstanceQ q(Module $R₂ $M) + have l₂ : qNF R₂ M := e₂.snd.snd.snd.snd.fst + let pf₂ : Q($rhs = NF.eval $(l₂.toNF)) := e₂.snd.snd.snd.snd.snd + /- Lift everything to the same scalar ring, `R`. -/ + let ⟨_, _, _, iRM, ⟨l₁', pf₁'⟩, ⟨l₂', pf₂'⟩, _⟩ ← qNF.matchRings iRM₁ _ iRM₂ l₁ l₂ q(0) q(0) + /- Construct a list of goals for the coefficientwise equality of these formal linear combinations, + and resolve our original goal (modulo these new goals). -/ + let (mvars, pf) ← reduceCoefficientwise iRM l₁' l₂' + g.assign q(NF.eq_of_eval_eq_eval $pf₁ $pf₂ $pf₁' $pf₂' $pf) + return mvars + +/-- Lemmas used to post-process the result of the `match_scalars` and `module` tactics by converting +the `algebraMap` operations which (which proliferate in the constructed scalar goals) to more +familiar forms: `ℕ`, `ℤ` and `ℚ` casts. -/ +def algebraMapThms : Array Name := #[``eq_natCast, ``eq_intCast, ``eq_ratCast] + +/-- Postprocessing for the scalar goals constructed in the `match_scalars` and `module` tactics. +These goals feature a proliferation of `algebraMap` operations (because the scalars start in `ℕ` and +get successively bumped up by `algebraMap`s as new semirings are encountered), so we reinterpret the +most commonly occuring `algebraMap`s (those out of `ℕ`, `ℤ` and `ℚ`) into their standard forms (`ℕ`, +`ℤ` and `ℚ` casts) and then try to disperse the casts using the various `push_cast` lemmas. -/ +def postprocess (mvarId : MVarId) : MetaM MVarId := do + -- collect the available `push_cast` lemmas + let mut thms : SimpTheorems := ← NormCast.pushCastExt.getTheorems + -- augment this list with the `algebraMapThms` lemmas, which handle `algebraMap` operations + for thm in algebraMapThms do + let ⟨levelParams, _, proof⟩ ← abstractMVars (mkConst thm) + thms ← thms.add (.stx (← mkFreshId) Syntax.missing) levelParams proof + -- now run `simp` with these lemmas, and (importantly) *no* simprocs + let ctx : Simp.Context := { + config := { failIfUnchanged := false } + simpTheorems := #[thms] + } + let (some r, _) ← simpTarget mvarId ctx (simprocs := #[]) | + throwError "internal error in match_scalars tactic: postprocessing should not close goals" + return r + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduce the goal to +the respective equalities of the `R`-coefficients of each atom. -/ +def matchScalars (g : MVarId) : MetaM (List MVarId) := do + let mvars ← AtomM.run .instances (matchScalarsAux g) + mvars.mapM postprocess + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduce the goal to +the respective equalities of the `R`-coefficients of each atom. + +For example, this produces the goal `⊢ a * 1 + b * 1 = (b + a) * 1`: +``` +example [AddCommMonoid M] [Semiring R] [Module R M] (a b : R) (x : M) : + a • x + b • x = (b + a) • x := by + match_scalars +``` +This produces the two goals `⊢ a * (a * 1) + b * (b * 1) = 1` (from the `x` atom) and +`⊢ a * -(b * 1) + b * (a * 1) = 0` (from the `y` atom): +``` +example [AddCommGroup M] [Ring R] [Module R M] (a b : R) (x : M) : + a • (a • x - b • y) + (b • a • y + b • b • x) = x := by + match_scalars +``` +This produces the goal `⊢ -2 * (a * 1) = a * (-2 * 1)`: +``` +example [AddCommGroup M] [Ring R] [Module R M] (a : R) (x : M) : + -(2:R) • a • x = a • (-2:ℤ) • x := by + match_scalars +``` +The scalar type for the goals produced by the `match_scalars` tactic is the largest scalar type +encountered; for example, if `ℕ`, `ℚ` and a characteristic-zero field `K` all occur as scalars, then +the goals produced are equalities in `K`. A variant of `push_cast` is used internally in +`match_scalars` to interpret scalars from the other types in this largest type. + +If the set of scalar types encountered is not totally ordered (in the sense that for all rings `R`, +`S` encountered, it holds that either `Algebra R S` or `Algebra S R`), then the `match_scalars` +tactic fails. +-/ +elab "match_scalars" : tactic => Tactic.liftMetaTactic matchScalars + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some commutative semiring `R`, and prove +the goal by checking that the LHS- and RHS-coefficients of each atom are the same up to +ring-normalization in `R`. + +(If the proofs of coefficient-wise equality will require more reasoning than just +ring-normalization, use the tactic `match_scalars` instead, and then prove coefficient-wise equality +by hand.) + +Example uses of the `module` tactic: +``` +example [AddCommMonoid M] [CommSemiring R] [Module R M] (a b : R) (x : M) : + a • x + b • x = (b + a) • x := by + module + +example [AddCommMonoid M] [Field K] [CharZero K] [Module K M] (x : M) : + (2:K)⁻¹ • x + (3:K)⁻¹ • x + (6:K)⁻¹ • x = x := by + module + +example [AddCommGroup M] [CommRing R] [Module R M] (a : R) (v w : M) : + (1 + a ^ 2) • (v + w) - a • (a • v - w) = v + (1 + a + a ^ 2) • w := by + module + +example [AddCommGroup M] [CommRing R] [Module R M] (a b μ ν : R) (x y : M) : + (μ - ν) • a • x = (a • μ • x + b • ν • y) - ν • (a • x + b • y) := by + module +``` +-/ +elab "module" : tactic => Tactic.liftMetaFinishingTactic fun g ↦ do + let l ← matchScalars g + discard <| l.mapM fun mvar ↦ AtomM.run .instances (Ring.proveEq mvar) + +end Mathlib.Tactic.Module diff --git a/Mathlib/Tactic/Ring/RingNF.lean b/Mathlib/Tactic/Ring/RingNF.lean index 4ac168ff6ec41..c538ee4c12311 100644 --- a/Mathlib/Tactic/Ring/RingNF.lean +++ b/Mathlib/Tactic/Ring/RingNF.lean @@ -147,7 +147,7 @@ partial def M.run ``rat_rawCast_neg, ``rat_rawCast_pos].foldlM (·.addConst · (post := false)) thms let ctx' := { ctx with simpTheorems := #[thms] } pure fun r' : Simp.Result ↦ do - r'.mkEqTrans (← Simp.main r'.expr ctx' (methods := ← Lean.Meta.Simp.mkDefaultMethods)).1 + r'.mkEqTrans (← Simp.main r'.expr ctx' (methods := Lean.Meta.Simp.mkDefaultMethodsCore {})).1 let nctx := { ctx, simp } let rec /-- The recursive context. -/ diff --git a/test/module.lean b/test/module.lean new file mode 100644 index 0000000000000..ee59dd02d0d9f --- /dev/null +++ b/test/module.lean @@ -0,0 +1,308 @@ +/- +Copyright (c) 2024 Heather Macbeth. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Heather Macbeth +-/ +import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.LinearCombination +import Mathlib.Tactic.Module +import Mathlib.Tactic.NoncommRing +import Mathlib.Tactic.Positivity + +/-! # Tests for the module-normalization tactic -/ + +open Mathlib.Tactic.LinearCombination + +variable {V : Type*} {K : Type*} {t u v w x y z : V} {a b c d e f μ ν ρ : K} + +/-! ### `ℕ` (most tests copied from the `abel` tactic) -/ + +section Nat +variable [AddCommMonoid V] + +example : x + (y + x) = x + x + y := by module +example : (3 : ℕ) • x = x + (2 : ℕ) • x := by module +example : 0 + x = x := by module +example (n : ℕ) : n • x = n • x := by module +example (n : ℕ) : 0 + n • x = n • x := by module +example : x + (y + (x + (z + (x + (u + (x + v)))))) = v + u + z + y + 4 • x := by module +example : x + y = y + x := by module +example : x + 2 • x = 2 • x + x := by module + +example : x + (y + x) = x + x + y ∨ False := by + left + module + +/-- +error: unsolved goals +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommMonoid V +⊢ 1 = 1 + +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommMonoid V +⊢ 1 = 2 * 1 +-/ +#guard_msgs in +example : x + y = x + 2 • y := by match_scalars + +/-- +error: ring failed, ring expressions not equal +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommMonoid V +⊢ 1 = 2 +-/ +#guard_msgs in +example : x + y = x + 2 • y := by module + +/-- error: goal x ≠ y is not an equality -/ +#guard_msgs in +example : x ≠ y := by module + +end Nat + +/-! ### `ℤ` (most tests copied from the `abel` tactic) -/ + +variable [AddCommGroup V] + +example : (x + y) - ((y + x) + x) = -x := by module +example : x - 0 = x := by module +example : (3 : ℤ) • x = x + (2 : ℤ) • x := by module +example : x - 2 • y = x - 2 • y := by module +example : (x + y) - ((y + x) + x) = -x := by module +example : x + y + (z + w - x) = y + z + w := by module +example : x + y + z + (z - x - x) = (-1) • x + y + 2 • z := by module +example : -x + x = 0 := by module +example : x - (0 - 0) = x := by module +example : x + (y - x) = y := by module +example : -y + (z - x) = z - y - x := by module + +example : x + y = y + x ∧ (↑((1:ℕ) + 1) : ℚ) = 2 := by + constructor + module -- do not focus this tactic: the double goal is the point of the test + guard_target =ₐ (↑((1:ℕ) + 1) : ℚ) = 2 + norm_cast + +-- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Interaction.20of.20abel.20with.20casting/near/319895001 +example : True := by + have : ∀ (p q r s : V), s + p - q = s - r - (q - r - p) := by + intro p q r s + module + trivial + +example : True := by + have : ∀ (p q r s : V), s + p - q = s - r - (q - r - p) := by + intro p q r s + match_scalars + · decide + · decide + · decide + · decide + trivial + +-- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Interaction.20of.20abel.20with.20casting/near/319897374 +example : y = x + z - (x - y + z) := by + have : True := trivial + module + +example : y = x + z - (x - y + z) := by + have : True := trivial + match_scalars <;> decide + +/-- +error: unsolved goals +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommGroup V +⊢ -1 + 1 = 0 +-/ +#guard_msgs in +example : -x + x = 0 := by + match_scalars + +/-! ### Commutative ring -/ + +section CommRing +variable [CommRing K] [Module K V] + +example : a • x + b • x = (a + b) • x := by module +example : a • x - b • x = (a - b) • x := by module +example : a • x - b • y = a • x + (-b) • y := by module +example : 2 • a • x = a • 2 • x := by module +example : a • x - b • y = a • x + (-b) • y := by module +example : (μ - ν) • a • x = (a • μ • x + b • ν • y) - ν • (a • x + b • y) := by module +example : (μ - ν) • b • y = μ • (a • x + b • y) - (a • μ • x + b • ν • y) := by module + +-- from https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/smul.20diamond/near/457163013 +example : (4 : ℤ) • v = (4 : K) • v := by module +example : (4 : ℕ) • v = (4 : K) • v := by module + +-- from https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/linear_combination.20for.20groups/near/437042918 +example : (1 + a ^ 2) • (v + w) - a • (a • v - w) = v + (1 + a + a ^ 2) • w := by module + +example (h : a = b) : a • x = b • x := by + match_scalars + linear_combination h + +/- `linear_combination` does not currently handle `•`. The following mimics what should eventually +be performed by a `linear_combination` call, with exact syntax TBD -- maybe +`linear_combination (norm := module) h • x` or `module_combination h • x`. -/ +example (h : a = b) : a • x = b • x := by + apply eq_of_add (congr($h • x):) + module + +example (h : a ^ 2 + b ^ 2 = 1) : a • (a • x - b • y) + (b • a • y + b • b • x) = x := by + match_scalars + · linear_combination h + · ring + +example (h : a ^ 2 + b ^ 2 = 1) : a • (a • x - b • y) + (b • a • y + b • b • x) = x := by + -- `linear_combination (norm := module) h • x` + apply eq_of_add (congr($h • x):) + module + +example (h1 : a • x + b • y = 0) (h2 : a • μ • x + b • ν • y = 0) : + (μ - ν) • a • x = 0 ∧ (μ - ν) • b • y = 0 := by + constructor + · -- `linear_combination (norm := module) h2 - ν • h1` + apply eq_of_add (congr($h2 - ν • $h1):) + module + · -- `linear_combination (norm := module) μ • h1 + h2` + apply eq_of_add (congr(μ • $h1 - $h2):) + module + +example (h1 : 0 • z + a • x + b • y = 0) (h2 : 0 • ρ • z + a • μ • x + b • ν • y = 0) : + (μ - ν) • a • x = 0 := by + -- `linear_combination (norm := module) h2 - ν • h1` + apply eq_of_add (congr($h2 - ν • $h1):) + module + +example + (h1 : a • x + b • y + c • z = 0) + (h2 : a • μ • x + b • ν • y + c • ρ • z = 0) + (h3 : a • μ • μ • x + b • ν • ν • y + c • ρ • ρ • z = 0) : + (μ - ν) • (μ - ρ) • a • x = 0 ∧ (μ - ν) • (ν - ρ) • b • y = 0 + ∧ (μ - ρ) • (ν - ρ) • c • z = 0 := by + refine ⟨?_, ?_, ?_⟩ + · -- `linear_combination (norm := module) h3 - (ν + ρ) • h2 + ν • ρ • h1` + apply eq_of_add (congr($h3 - (ν + ρ) • $h2 + ν • ρ • $h1):) + module + · -- `linear_combination (norm := module) - h3 + (μ + ρ) • h2 - μ • ρ • h1` + apply eq_of_add (congr(- $h3 + (μ + ρ) • $h2 - μ • ρ • $h1):) + module + · -- `linear_combination (norm := module) h3 - (μ + ν) • h2 + μ • ν • h1` + apply eq_of_add (congr($h3 - (μ + ν) • $h2 + μ • ν • $h1):) + module + +/-- +error: ring failed, ring expressions not equal +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝² : AddCommGroup V +inst✝¹ : CommRing K +inst✝ : Module K V +⊢ a * 2 = 2 +-/ +#guard_msgs in +example : 2 • a • x = 2 • x := by module + +end CommRing + +/-! ### (Noncommutative) ring -/ + +section Ring +variable [Ring K] [Module K V] + +example : a • x + b • x = (b + a) • x := by + match_scalars + noncomm_ring + +example : 2 • a • x = a • (2:ℤ) • x := by + match_scalars + noncomm_ring + +example (h : a = b) : a • x = b • x := by + match_scalars + simp [h] + +example : (a - b) • a • x + b • b • x = a • a • x + b • (-a + b) • x := by + match_scalars + noncomm_ring + +end Ring + +/-! ### Characteristic-zero field -/ + +section CharZeroField +variable [Field K] [CharZero K] [Module K V] + +example : (2:K)⁻¹ • x + (3:K)⁻¹ • x + (6:K)⁻¹ • x = x := by module + +example (h₁ : t - u = -(v - w)) (h₂ : t + u = v + w) : t = w := by + -- `linear_combination (norm := module) 2⁻¹ • h₁ + 2⁻¹ • h₂` + apply eq_of_add (congr((2:K)⁻¹ • $h₁ + (2:K)⁻¹ • $h₂):) + module + +end CharZeroField + +/-! ### Linearly ordered field -/ + +section LinearOrderedField +variable [LinearOrderedField K] [Module K V] + +example (ha : 0 ≤ a) (hb : 0 < b) : + x = (a / (a + b)) • y + (b / (a + b)) • (x + (a / b) • (x - y)) := by + match_scalars + · field_simp + ring + · field_simp + ring + +-- From Analysis.Convex.StoneSeparation +example (hab : 0 < a * b + c * d) : + (a * b / (a * b + c * d) * e) • u + (c * d / (a * b + c * d) * f) • v + + ((a * b / (a * b + c * d)) • d • x + (c * d / (a * b + c * d)) • b • y) = + (a * b + c * d)⁻¹ • ((a * b * e) • u + ((c * d * f) • v + + ((a * b) • d • x + (c * d) • b • y))) := by + match_scalars + · field_simp + · field_simp + · field_simp + · field_simp + +example (h₁ : 1 = a ^ 2 + b ^ 2) (h₂ : 1 - a ≠ 0) : + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • (4:K) • ((2 / (1 - a)) • y) + + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • ((2 / (1 - a)) ^ 2 * b ^ 2 - 4) • x + = a • x + y := by + -- `linear_combination (norm := skip) (h₁ * (b ^ 2 + (1 - a) ^ 2)⁻¹) • (y + (a - 1) • x)` + apply eq_of_add (congr(($h₁ * (b ^ 2 + (1 - a) ^ 2)⁻¹) • (y + (a - 1) • x)):) + match_scalars + · field_simp + ring + · field_simp + ring + +example (h₁ : 1 = a ^ 2 + b ^ 2) (h₂ : 1 - a ≠ 0) : + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • (4:K) • ((2 / (1 - a)) • y) + + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • ((2 / (1 - a)) ^ 2 * b ^ 2 - 4) • x + = a • x + y := by + match_scalars + · field_simp + linear_combination 4 * (1 - a) * h₁ + · field_simp + linear_combination 4 * (a - 1) ^ 3 * h₁ + +end LinearOrderedField From 4591e55bbcc5a0ff893487a5a8db65953909ea48 Mon Sep 17 00:00:00 2001 From: Emily Riehl Date: Wed, 25 Sep 2024 09:39:53 +0000 Subject: [PATCH 145/170] feat(CategoryTheory): simps for `conjugateEquiv` plus computable `conjugateIsoEquiv` (#17108) The term `conjugateIsoEquiv` is redefined to make it computable, cutting asIso and explicitly constructing the required inverse isomorphisms. In parallel, additional simps are added to `conjugateEquiv` so that we can later use `conjugateEquiv` and `conjugateIsoEquiv` instead of `Adjunction.natTransEquiv` and `Adjunction.natIsoEquiv` (see #17113). Co-authored-by: [Dagur Asgeirsson](https://github.com/dagurtomas) --- Mathlib/CategoryTheory/Adjunction/Mates.lean | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Mathlib/CategoryTheory/Adjunction/Mates.lean b/Mathlib/CategoryTheory/Adjunction/Mates.lean index 1353ea9022b78..fa2243dda407c 100644 --- a/Mathlib/CategoryTheory/Adjunction/Mates.lean +++ b/Mathlib/CategoryTheory/Adjunction/Mates.lean @@ -328,6 +328,7 @@ Furthermore, this bijection preserves (and reflects) isomorphisms, i.e. a transf iff its image under the bijection is an iso, see eg `CategoryTheory.conjugateIsoEquiv`. This is in contrast to the general case `mateEquiv` which does not in general have this property. -/ +@[simps!] def conjugateEquiv : (L₂ ⟶ L₁) ≃ (R₁ ⟶ R₂) := calc (L₂ ⟶ L₁) ≃ _ := (Iso.homCongr L₂.leftUnitor L₁.rightUnitor).symm @@ -401,6 +402,7 @@ variable [Category.{v₁} C] [Category.{v₂} D] variable {L₁ L₂ L₃ : C ⥤ D} {R₁ R₂ R₃ : D ⥤ C} variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : L₃ ⊣ R₃) +@[simp] theorem conjugateEquiv_comp (α : L₂ ⟶ L₁) (β : L₃ ⟶ L₂) : conjugateEquiv adj₁ adj₂ α ≫ conjugateEquiv adj₂ adj₃ β = conjugateEquiv adj₁ adj₃ (β ≫ α) := by @@ -414,6 +416,7 @@ theorem conjugateEquiv_comp (α : L₂ ⟶ L₁) (β : L₃ ⟶ L₂) : simp only [comp_id, id_comp, assoc, map_comp] at vcompd ⊢ rw [vcompd] +@[simp] theorem conjugateEquiv_symm_comp (α : R₁ ⟶ R₂) (β : R₂ ⟶ R₃) : (conjugateEquiv adj₂ adj₃).symm β ≫ (conjugateEquiv adj₁ adj₂).symm α = (conjugateEquiv adj₁ adj₃).symm (α ≫ β) := by @@ -473,9 +476,16 @@ theorem conjugateEquiv_symm_of_iso (α : R₁ ⟶ R₂) infer_instance /-- Thus conjugation defines an equivalence between natural isomorphisms. -/ -noncomputable def conjugateIsoEquiv : (L₂ ≅ L₁) ≃ (R₁ ≅ R₂) where - toFun α := asIso (conjugateEquiv adj₁ adj₂ α.hom) - invFun β := asIso ((conjugateEquiv adj₁ adj₂).symm β.hom) +@[simps] +def conjugateIsoEquiv : (L₂ ≅ L₁) ≃ (R₁ ≅ R₂) where + toFun α := { + hom := conjugateEquiv adj₁ adj₂ α.hom + inv := conjugateEquiv adj₂ adj₁ α.inv + } + invFun β := { + hom := (conjugateEquiv adj₁ adj₂).symm β.hom + inv := (conjugateEquiv adj₂ adj₁).symm β.inv + } left_inv := by aesop_cat right_inv := by aesop_cat From 2ab87b42bb0c15f6fe9c94b1459e9b8746006d73 Mon Sep 17 00:00:00 2001 From: Ira Fesefeldt Date: Wed, 25 Sep 2024 12:08:02 +0000 Subject: [PATCH 146/170] doc: Improve documentation of ordinal-indexed approximations (#16406) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As mentioned in #15522, the documentation uses heavily the wording "ordinal approximation", which suggests that ordinals are approximated. This PR changes it to "ordinal-indexed approximation" and highlights the indexed nature of ordinals in various places. It also fixes some apparent then vs than errors. I appreciate any suggestions to further improve the documentation and hints for spelling mistakes. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) Co-authored-by: Violeta Hernández Co-authored-by: Ira Fesefeldt --- .../Ordinal/FixedPointApproximants.lean | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean index 7cb80b64b2db5..e7baa70d5b32b 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean @@ -8,7 +8,7 @@ import Mathlib.SetTheory.Ordinal.Arithmetic /-! # Ordinal Approximants for the Fixed points on complete lattices -This file sets up the ordinal approximation theory of fixed points +This file sets up the ordinal-indexed approximation theory of fixed points of a monotone function in a complete lattice [Cousot1979]. The proof follows loosely the one from [Echenique2005]. @@ -17,15 +17,15 @@ ordinals from mathlib. It still allows an approximation scheme indexed over the ## Main definitions -* `OrdinalApprox.lfpApprox`: The ordinal approximation of the least fixed point - greater or equal then an initial value of a bundled monotone function. -* `OrdinalApprox.gfpApprox`: The ordinal approximation of the greatest fixed point - less or equal then an initial value of a bundled monotone function. +* `OrdinalApprox.lfpApprox`: The ordinal-indexed approximation of the least fixed point + greater or equal than an initial value of a bundled monotone function. +* `OrdinalApprox.gfpApprox`: The ordinal-indexed approximation of the greatest fixed point + less or equal than an initial value of a bundled monotone function. ## Main theorems -* `OrdinalApprox.lfp_mem_range_lfpApprox`: The approximation of +* `OrdinalApprox.lfp_mem_range_lfpApprox`: The ordinal-indexed approximation of the least fixed point eventually reaches the least fixed point -* `OrdinalApprox.gfp_mem_range_gfpApprox`: The approximation of +* `OrdinalApprox.gfp_mem_range_gfpApprox`: The ordinal-indexed approximation of the greatest fixed point eventually reaches the greatest fixed point ## References @@ -67,7 +67,9 @@ variable [CompleteLattice α] (f : α →o α) (x : α) open Function fixedPoints Cardinal Order OrderHom set_option linter.unusedVariables false in -/-- Ordinal approximants of the least fixed point greater then an initial value x -/ +/-- The ordinal-indexed sequence approximating the least fixed point greater than +an initial value `x`. It is defined in such a way that we have `lfpApprox 0 x = x` and +`lfpApprox a x = ⨆ b < a, f (lfpApprox b x)`. -/ def lfpApprox (a : Ordinal.{u}) : α := sSup ({ f (lfpApprox b) | (b : Ordinal) (h : b < a) } ∪ {x}) termination_by a @@ -110,8 +112,7 @@ theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : simp only [Set.mem_setOf_eq] use a -/-- The ordinal approximants of the least fixed point are stabilizing - when reaching a fixed point of f -/ +/-- The approximations of the least fixed point stabilize at a fixed point of `f` -/ theorem lfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : x ≤ f x) (h_ab : a ≤ b) (h : lfpApprox f x a ∈ fixedPoints f) : lfpApprox f x b = lfpApprox f x a := by rw [mem_fixedPoints_iff] at h @@ -131,8 +132,8 @@ theorem lfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : x ≤ f x) (h_ · rw [IH a' ha'b (le_of_not_lt haa), h] · exact lfpApprox_monotone f x h_ab -/-- There are distinct ordinals smaller than the successor of the domains cardinals - with equal value -/ +/-- There are distinct indices smaller than the successor of the domain's cardinality +yielding the same value -/ theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| succ #α, a ≠ b ∧ lfpApprox f x a = lfpApprox f x b := by have h_ninj := not_injective_limitation_set <| lfpApprox f x @@ -144,8 +145,8 @@ theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| · intro h_eq; rw [Subtype.coe_inj] at h_eq; exact h_nab h_eq · exact h_fab -/-- If there are distinct ordinals with equal value then - every value succeeding the smaller ordinal are fixed points -/ +/-- If the sequence of ordinal-indexed approximations takes a value twice, +then it actually stabilised at that value. -/ lemma lfpApprox_mem_fixedPoints_of_eq {a b c : Ordinal} (h_init : x ≤ f x) (h_ab : a < b) (h_ac : a ≤ c) (h_fab : lfpApprox f x a = lfpApprox f x b) : lfpApprox f x c ∈ fixedPoints f := by @@ -159,7 +160,7 @@ lemma lfpApprox_mem_fixedPoints_of_eq {a b c : Ordinal} · exact h_ac · exact lfpApprox_mem_fixedPoint -/-- A fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/ theorem lfpApprox_ord_mem_fixedPoint (h_init : x ≤ f x) : lfpApprox f x (ord <| succ #α) ∈ fixedPoints f := by let ⟨a, h_a, b, h_b, h_nab, h_fab⟩ := exists_lfpApprox_eq_lfpApprox f x @@ -171,8 +172,8 @@ theorem lfpApprox_ord_mem_fixedPoint (h_init : x ≤ f x) : exact lfpApprox_mem_fixedPoints_of_eq f x h_init (h_nab.symm.lt_of_le h_ba) (le_of_lt h_b) (h_fab.symm) -/-- Every value of the ordinal approximants are less or equal than every fixed point of f greater - then the initial value -/ +/-- Every value of the approximation is less or equal than every fixed point of `f` +greater or equal than the initial value -/ theorem lfpApprox_le_of_mem_fixedPoints {a : α} (h_a : a ∈ fixedPoints f) (h_le_init : x ≤ a) (i : Ordinal) : lfpApprox f x i ≤ a := by induction i using Ordinal.induction with @@ -192,7 +193,8 @@ theorem lfpApprox_le_of_mem_fixedPoints {a : α} rw [h_y] exact h_le_init -/-- The least fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation sequence converges at the successor of the domain's cardinality +to the least fixed point if starting from `⊥` -/ theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = lfp f := by apply le_antisymm · have h_lfp : ∃ y : fixedPoints f, lfp f = y := by use ⊥; exact rfl @@ -204,13 +206,15 @@ theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = lfp f := by let ⟨x, h_x⟩ := h_fix; rw [h_x] exact lfp_le_fixed f x.prop -/-- Some ordinal approximation of the least fixed point is the least fixed point. -/ +/-- Some approximation of the least fixed point starting from `⊥` is the least fixed point. -/ theorem lfp_mem_range_lfpApprox : lfp f ∈ Set.range (lfpApprox f ⊥) := by use ord <| succ #α exact lfpApprox_ord_eq_lfp f set_option linter.unusedVariables false in -/-- Ordinal approximants of the greatest fixed point -/ +/-- The ordinal-indexed sequence approximating the greatest fixed point greater than +an initial value `x`. It is defined in such a way that we have `gfpApprox 0 x = x` and +`gfpApprox a x = ⨅ b < a, f (lfpApprox b x)`. -/ def gfpApprox (a : Ordinal.{u}) : α := sInf ({ f (gfpApprox b) | (b : Ordinal) (h : b < a) } ∪ {x}) termination_by a @@ -230,34 +234,35 @@ theorem gfpApprox_add_one (h : f x ≤ x) (a : Ordinal) : gfpApprox f x (a+1) = f (gfpApprox f x a) := lfpApprox_add_one (OrderHom.dual f) x h a -/-- The ordinal approximants of the least fixed point are stabilizing - when reaching a fixed point of f -/ + +/-- The approximations of the greatest fixed point stabilize at a fixed point of `f` -/ theorem gfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : f x ≤ x) (h_ab : a ≤ b) (h : gfpApprox f x a ∈ fixedPoints f) : gfpApprox f x b = gfpApprox f x a := lfpApprox_eq_of_mem_fixedPoints (OrderHom.dual f) x h_init h_ab h -/-- There are distinct ordinals smaller than the successor of the domains cardinals with - equal value -/ +/-- There are distinct indices smaller than the successor of the domain's cardinality +yielding the same value -/ theorem exists_gfpApprox_eq_gfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| succ #α, a ≠ b ∧ gfpApprox f x a = gfpApprox f x b := exists_lfpApprox_eq_lfpApprox (OrderHom.dual f) x -/-- A fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/ lemma gfpApprox_ord_mem_fixedPoint (h_init : f x ≤ x) : gfpApprox f x (ord <| succ #α) ∈ fixedPoints f := lfpApprox_ord_mem_fixedPoint (OrderHom.dual f) x h_init -/-- Every value of the ordinal approximants are greater or equal than every fixed point of f - that is smaller then the initial value -/ +/-- Every value of the approximation is greater or equal than every fixed point of `f` +less or equal than the initial value -/ lemma le_gfpApprox_of_mem_fixedPoints {a : α} (h_a : a ∈ fixedPoints f) (h_le_init : a ≤ x) (i : Ordinal) : a ≤ gfpApprox f x i := lfpApprox_le_of_mem_fixedPoints (OrderHom.dual f) x h_a h_le_init i -/-- The greatest fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation sequence converges at the successor of the domain's cardinality +to the greatest fixed point if starting from `⊥` -/ theorem gfpApprox_ord_eq_gfp : gfpApprox f ⊤ (ord <| succ #α) = gfp f := lfpApprox_ord_eq_lfp (OrderHom.dual f) -/-- Some ordinal approximation of the greatest fixed point is the greatest fixed point. -/ +/-- Some approximation of the least fixed point starting from `⊤` is the greatest fixed point. -/ theorem gfp_mem_range_gfpApprox : gfp f ∈ Set.range (gfpApprox f ⊤) := lfp_mem_range_lfpApprox (OrderHom.dual f) From ecabe92400d54dd3330179535bc6cc65ef655ced Mon Sep 17 00:00:00 2001 From: grunweg Date: Wed, 25 Sep 2024 13:22:45 +0000 Subject: [PATCH 147/170] chore(Symmetric/FundamentalTheorem): omit unused `Fintype` assumption (#17126) Found by the linter in #10235. --- .../RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean b/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean index 4d835d7c912f4..b003422369bc5 100644 --- a/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean +++ b/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean @@ -235,6 +235,7 @@ lemma supDegree_esymmAlgHomMonomial (hr : r ≠ 0) (t : Fin n →₀ ℕ) (hnm : · exact (monic_esymm this).pow toLex_add toLex.injective · rwa [Ne, ← leadingCoeff_eq_zero toLex.injective, leadingCoeff_esymmAlgHomMonomial _ hnm] +omit [Fintype σ] in lemma IsSymmetric.antitone_supDegree [LinearOrder σ] {p : MvPolynomial σ R} (hp : p.IsSymmetric) : Antitone ↑(ofLex <| p.supDegree toLex) := by obtain rfl | h0 := eq_or_ne p 0 From c7dedd662f7e7e77cc0adc154e4ef928c9113e88 Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 25 Sep 2024 13:34:40 +0000 Subject: [PATCH 148/170] feat: the docPrime linter (#16694) This syntax linter emits a warning on declarations whose name ends with a `'` and that have no doc-string. By default, the linter is * `on` on `mathlib` and * `off` on projects depending on mathlib. The file `scripts/no_lints_prime_decls.txt` contains the current exceptions. The exceptions need to be managed manually by design: the expectation is that, once the linter starts, the nolints file should only decrease and never increase. In particular, after the linter flags a declaration, simply adding manually an exception is *not enough* for CI to be successful. There needs to be a change in the file with the exception (or upstream from it), since otherwise `lake` will replay the `olean`s and keep emitting the initial warning. The expectation is that the change will be the addition of a doc-string. Co-authored-by: Michael Rothgang --- Mathlib.lean | 1 + Mathlib/Init.lean | 1 + Mathlib/Tactic.lean | 1 + Mathlib/Tactic/Linter/DocPrime.lean | 73 + lakefile.lean | 1 + scripts/no_lints_prime_decls.txt | 4879 +++++++++++++++++++++++++++ test/DocPrime.lean | 80 + 7 files changed, 5036 insertions(+) create mode 100644 Mathlib/Tactic/Linter/DocPrime.lean create mode 100644 scripts/no_lints_prime_decls.txt create mode 100644 test/DocPrime.lean diff --git a/Mathlib.lean b/Mathlib.lean index df6d075a2c08a..07a75add2567f 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4272,6 +4272,7 @@ import Mathlib.Tactic.LinearCombination' import Mathlib.Tactic.LinearCombination.Lemmas import Mathlib.Tactic.Linter import Mathlib.Tactic.Linter.AdmitLinter +import Mathlib.Tactic.Linter.DocPrime import Mathlib.Tactic.Linter.FlexibleLinter import Mathlib.Tactic.Linter.GlobalAttributeIn import Mathlib.Tactic.Linter.HashCommandLinter diff --git a/Mathlib/Init.lean b/Mathlib/Init.lean index fc6135c7832d0..dff297db373ea 100644 --- a/Mathlib/Init.lean +++ b/Mathlib/Init.lean @@ -1,3 +1,4 @@ +import Mathlib.Tactic.Linter.DocPrime import Mathlib.Tactic.Linter.HashCommandLinter import Mathlib.Tactic.Linter.GlobalAttributeIn -- This file imports Batteries.Tactic.Lint, where the `env_linter` attribute is defined. diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index 153a66d29d73b..ee548f7d6b975 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -134,6 +134,7 @@ import Mathlib.Tactic.LinearCombination' import Mathlib.Tactic.LinearCombination.Lemmas import Mathlib.Tactic.Linter import Mathlib.Tactic.Linter.AdmitLinter +import Mathlib.Tactic.Linter.DocPrime import Mathlib.Tactic.Linter.FlexibleLinter import Mathlib.Tactic.Linter.GlobalAttributeIn import Mathlib.Tactic.Linter.HashCommandLinter diff --git a/Mathlib/Tactic/Linter/DocPrime.lean b/Mathlib/Tactic/Linter/DocPrime.lean new file mode 100644 index 0000000000000..86b12eaad3719 --- /dev/null +++ b/Mathlib/Tactic/Linter/DocPrime.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2024 Damiano Testa. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damiano Testa +-/ +import Lean.Elab.Command + +/-! +# The "docPrime" linter + +The "docPrime" linter emits a warning on declarations that have no doc-string and whose +name ends with a `'`. Such declarations are expected to have a documented explanation +for the presence of a `'` in their name. This may consist of discussion of the difference relative +to an unprimed version of that declaration, or an explanation as to why no better naming scheme +is possible. +-/ + +open Lean Elab + +namespace Mathlib.Linter + +/-- +The "docPrime" linter emits a warning on declarations that have no doc-string and whose +name ends with a `'`. + +The file `scripts/no_lints_prime_decls.txt` contains a list of temporary exceptions to this linter. +This list should not be appended to, and become emptied over time. +-/ +register_option linter.docPrime : Bool := { + defValue := false + descr := "enable the docPrime linter" +} + +namespace DocPrime + +@[inherit_doc Mathlib.Linter.linter.docPrime] +def docPrimeLinter : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.docPrime (← getOptions) do + return + if (← get).messages.hasErrors then + return + unless [``Lean.Parser.Command.declaration, `lemma].contains stx.getKind do return + let docstring := stx[0][0] + -- The current declaration's id, possibly followed by a list of universe names. + let declId := + if stx[1].isOfKind ``Lean.Parser.Command.instance then + stx[1][3][0] + else + stx[1][1] + -- The name of the current declaration, with namespaces resolved. + let declName := + if let `_root_ :: rest := declId[0].getId.components then + rest.foldl (· ++ ·) default + else (← getCurrNamespace) ++ declId[0].getId + let msg := m!"`{declName}` is missing a doc-string, please add one.\n\ + Declarations whose name ends with a `'` are expected to contain an explanation for the \ + presence of a `'` in their doc-string. This may consist of discussion of the difference \ + relative to the unprimed version, or an explanation as to why no better naming scheme \ + is possible." + if docstring[0][1].getAtomVal.isEmpty && declName.toString.back == '\'' then + if ← System.FilePath.pathExists "scripts/no_lints_prime_decls.txt" then + if (← IO.FS.lines "scripts/no_lints_prime_decls.txt").contains declName.toString then + return + else + Linter.logLint linter.docPrime declId msg + else + Linter.logLint linter.docPrime declId msg + +initialize addLinter docPrimeLinter + +end DocPrime + +end Mathlib.Linter diff --git a/lakefile.lean b/lakefile.lean index 086cd93292deb..601346ee071d0 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -25,6 +25,7 @@ require "leanprover-community" / "LeanSearchClient" @ git "main" (as well as `Archive`, `Counterexamples` and `test`). -/ abbrev mathlibOnlyLinters : Array LeanOption := #[ + ⟨`linter.docPrime, true⟩, ⟨`linter.hashCommand, true⟩, ⟨`linter.oldObtain, true,⟩, ⟨`linter.refine, true⟩, diff --git a/scripts/no_lints_prime_decls.txt b/scripts/no_lints_prime_decls.txt new file mode 100644 index 0000000000000..048a285c74a49 --- /dev/null +++ b/scripts/no_lints_prime_decls.txt @@ -0,0 +1,4879 @@ +AbelRuffini.not_solvable_by_rad' +abs_add' +abs_le_of_sq_le_sq' +abs_lt_of_sq_lt_sq' +abs_norm' +abs_norm_sub_norm_le' +Absorbent.zero_mem' +ack_strict_mono_left' +Action.inhabited' +Action.tensorUnit_ρ' +Action.tensor_ρ' +AddAction.orbitZMultiplesEquiv_symm_apply' +AddChar.div_apply' +AddChar.inv_apply' +AddChar.neg_apply' +AddChar.sub_apply' +AddChar.zmodChar_apply' +AddCircle.addOrderOf_div_of_gcd_eq_one' +AddCircle.continuous_mk' +AddCircle.measurable_mk' +AddCircle.norm_eq' +AddCommGroup.intCast_modEq_intCast' +AddCommGroup.ModEq.add_left_cancel' +AddCommGroup.ModEq.add_right_cancel' +AddCommGroup.modEq_sub_iff_add_modEq' +AddCommGroup.ModEq.sub_left_cancel' +AddCommGroup.ModEq.sub_right_cancel' +AddCommGroup.sub_modEq_iff_modEq_add' +AddConstMapClass.map_add_int' +AddConstMapClass.map_add_nat' +AddConstMapClass.map_add_ofNat' +AddConstMapClass.map_int_add' +AddConstMapClass.map_nat' +AddConstMapClass.map_nat_add' +AddConstMapClass.map_ofNat' +AddConstMapClass.map_ofNat_add' +AddConstMapClass.map_sub_int' +AddConstMapClass.map_sub_nat' +AddConstMapClass.map_sub_ofNat' +add_div' +AddGroup.int_smulCommClass' +Additive.isometricVAdd' +Additive.isometricVAdd'' +add_le_mul' +AddMonoidAlgebra.lift_apply' +AddMonoidAlgebra.lift_of' +AddMonoidAlgebra.lift_unique' +AddMonoidAlgebra.mem_grade_iff' +AddMonoidHom.coe_smul' +AddMonoidHom.coe_toMultiplicative' +AddMonoidHom.coe_toMultiplicative'' +AddMonoid.nat_smulCommClass' +add_sq' +AddSubgroup.torsionBy.mod_self_nsmul' +AddValuation.map_add' +AddValuation.map_lt_sum' +ADEInequality.admissible_A' +ADEInequality.admissible_D' +ADEInequality.admissible_of_one_lt_sumInv_aux' +AdjoinRoot.algebraMap_eq' +AdjoinRoot.coe_injective' +AdjoinRoot.isIntegral_root' +AdjoinRoot.Minpoly.toAdjoin_apply' +AEMeasurable.comp_aemeasurable' +aemeasurable_const' +AEMeasurable.const_smul' +AEMeasurable.div' +aemeasurable_id' +aemeasurable_id'' +AEMeasurable.inf' +AEMeasurable.mono' +AEMeasurable.mul' +aemeasurable_of_tendsto_metrizable_ae' +AEMeasurable.sup' +AffineEquiv.coe_mk' +AffineEquiv.linear_mk' +AffineIsometryEquiv.coe_mk' +AffineIsometryEquiv.coe_vaddConst' +AffineIsometryEquiv.dist_pointReflection_self' +AffineIsometryEquiv.linearIsometryEquiv_mk' +AffineMap.coe_mk' +AffineMap.lineMap_apply_module' +AffineMap.lineMap_apply_ring' +AffineSubspace.mem_perpBisector_iff_dist_eq' +AkraBazziRecurrence.asympBound_def' +AkraBazziRecurrence.dist_r_b' +Algebra.adjoin_induction'' +Algebra.algebraMap_eq_smul_one' +Algebra.fg_trans' +Algebra.FormallyUnramified.ext' +Algebra.FormallyUnramified.lift_unique' +Algebra.Generators.Cotangent.module' +Algebra.Generators.Cotangent.val_smul' +Algebra.Generators.Cotangent.val_smul'' +Algebra.Generators.Cotangent.val_smul''' +AlgebraicClosure.toStepOfLE' +AlgebraicGeometry.basicOpen_eq_of_affine' +AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_basicOpen' +AlgebraicGeometry.IsAffineOpen.isLocalization_stalk' +AlgebraicGeometry.IsOpenImmersion.hasLimit_cospan_forget_of_left' +AlgebraicGeometry.IsOpenImmersion.hasLimit_cospan_forget_of_right' +AlgebraicGeometry.LocallyRingedSpace.Hom.ext' +AlgebraicGeometry.LocallyRingedSpace.id_val' +AlgebraicGeometry.LocallyRingedSpace.stalkMap_germ' +AlgebraicGeometry.morphismRestrict_app' +AlgebraicGeometry.PresheafedSpace.GlueData.opensImagePreimageMap_app' +AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.c_iso' +AlgebraicGeometry.PresheafedSpace.stalkMap_germ' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.add_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.mul_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.neg_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.one_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.zero_mem' +AlgebraicGeometry.ProjIsoSpecTopComponent.FromSpec.mem_carrier_iff' +AlgebraicGeometry.Proj.stalkIso'_germ' +AlgebraicGeometry.Scheme.Hom.appIso_hom' +AlgebraicGeometry.Scheme.Hom.appLE_map' +AlgebraicGeometry.Scheme.Hom.map_appLE' +AlgebraicGeometry.Scheme.map_basicOpen' +AlgebraicGeometry.Scheme.mem_basicOpen_top' +AlgebraicGeometry.Scheme.Opens.germ_stalkIso_hom' +AlgebraicGeometry.Scheme.stalkMap_germ' +AlgebraicGeometry.SheafedSpace.comp_c_app' +AlgebraicGeometry.SheafedSpace.IsOpenImmersion.hasLimit_cospan_forget_of_left' +AlgebraicGeometry.SheafedSpace.IsOpenImmersion.hasLimit_cospan_forget_of_right' +AlgebraicGeometry.Spec.locallyRingedSpaceObj_presheaf' +AlgebraicGeometry.Spec.locallyRingedSpaceObj_presheaf_map' +AlgebraicGeometry.Spec.locallyRingedSpaceObj_sheaf' +AlgebraicGeometry.stalkToFiberRingHom_germ' +AlgebraicGeometry.StructureSheaf.comap_id' +AlgebraicGeometry.StructureSheaf.const_apply' +AlgebraicGeometry.StructureSheaf.const_mul_cancel' +AlgebraicGeometry.StructureSheaf.IsFraction.eq_mk' +AlgebraicGeometry.StructureSheaf.localizationToStalk_mk' +AlgebraicGeometry.StructureSheaf.res_const' +AlgebraicGeometry.StructureSheaf.stalkToFiberRingHom_germ' +AlgebraicGeometry.StructureSheaf.toBasicOpen_mk' +AlgebraicGeometry.ΓSpec.adjunction_counit_app' +AlgebraicGeometry.ΓSpec.locallyRingedSpaceAdjunction_counit_app' +AlgebraicGeometry.ΓSpec.locallyRingedSpaceAdjunction_homEquiv_apply' +AlgebraicGeometry.ΓSpec.toOpen_unit_app_val_c_app' +algebraicIndependent_equiv' +AlgebraicIndependent.map' +AlgebraicIndependent.to_subtype_range' +AlgebraicTopology.DoldKan.hσ'_eq' +AlgebraicTopology.DoldKan.Γ₀.Obj.map_on_summand' +AlgebraicTopology.DoldKan.Γ₀.Obj.map_on_summand₀' +AlgebraicTopology.DoldKan.Γ₀.Obj.Termwise.mapMono_δ₀' +Algebra.IsAlgebraic.bijective_of_isScalarTower' +Algebra.TensorProduct.algebraMap_apply' +Algebra.TensorProduct.basis_repr_symm_apply' +Algebra.TensorProduct.ext' +Algebra.TensorProduct.intCast_def' +Algebra.TensorProduct.natCast_def' +Algebra.toMatrix_lmul' +AlgEquiv.apply_smulCommClass' +AlgEquiv.coe_restrictScalars' +AlgEquiv.coe_ringEquiv' +AlgEquiv.mk_coe' +AlgHom.coe_mk' +AlgHom.coe_restrictScalars' +AlgHom.toAddMonoidHom' +AlgHom.toMonoidHom' +AlternatingMap.domCoprod.summand_mk'' +analyticOn_congr' +AnalyticOn.congr' +AnalyticOn.eval_continuousLinearMap' +AnalyticOn.eval_linearMap' +AntilipschitzWith.le_mul_nnnorm' +AntilipschitzWith.le_mul_norm' +AntilipschitzWith.to_rightInvOn' +antisymm' +Antitone.const_mul' +Antitone.mul_const' +AntitoneOn.const_mul' +AntitoneOn.mul_const' +Applicative.pure_seq_eq_map' +ApplicativeTransformation.preserves_map' +apply_abs_le_mul_of_one_le' +ArithmeticFunction.mul_smul' +ArithmeticFunction.one_smul' +ArithmeticFunction.ppow_succ' +ArithmeticFunction.sum_eq_iff_sum_smul_moebius_eq_on' +Associated.dvd' +Associated.of_pow_associated_of_prime' +Associates.count_mul_of_coprime' +Associates.dvd_of_mem_factors' +Associates.map_subtype_coe_factors' +Associates.mk_ne_zero' +Associates.unique' +Asymptotics.IsBigO.congr' +Asymptotics.isBigO_const_mul_left_iff' +Asymptotics.IsBigO.const_mul_right' +Asymptotics.isBigO_const_mul_right_iff' +Asymptotics.isBigO_fst_prod' +Asymptotics.IsBigO.of_bound' +Asymptotics.isBigO_of_le' +Asymptotics.isBigO_self_const_mul' +Asymptotics.isBigO_snd_prod' +Asymptotics.IsBigOWith.congr' +Asymptotics.IsBigOWith.const_mul_right' +Asymptotics.isBigOWith_of_le' +Asymptotics.IsBigOWith.pow' +Asymptotics.isBigOWith_self_const_mul' +Asymptotics.IsBigOWith.sup' +Asymptotics.isBigOWith_zero' +Asymptotics.isEquivalent_of_tendsto_one' +Asymptotics.IsLittleO.congr' +Asymptotics.isLittleO_const_mul_left_iff' +Asymptotics.IsLittleO.const_mul_right' +Asymptotics.isLittleO_const_mul_right_iff' +Asymptotics.IsLittleO.def' +Asymptotics.isLittleO_iff_nat_mul_le' +Asymptotics.isLittleO_iff_tendsto' +Asymptotics.isLittleO_irrefl' +Asymptotics.IsLittleO.right_isBigO_add' +Asymptotics.IsLittleO.right_isTheta_add' +Asymptotics.isTheta_of_norm_eventuallyEq' +Asymptotics.SuperpolynomialDecay.congr' +ball_eq' +Ballot.ballot_problem' +Basis.det_map' +Basis.det_reindex' +Basis.mk_eq_rank' +Basis.mk_eq_rank'' +Basis.reindexRange_repr' +Basis.repr_eq_iff' +Basis.tensorProduct_apply' +Behrend.bound_aux' +Behrend.lower_bound_le_one' +Behrend.map_succ' +bernoulli'_def' +bernoulli'_spec' +bernoulli_spec' +bernsteinPolynomial.flip' +Besicovitch.SatelliteConfig.hlast' +Besicovitch.SatelliteConfig.inter' +bihimp_eq' +biInf_congr' +biInf_finsetSigma' +biInf_sigma' +Bimod.AssociatorBimod.hom_left_act_hom' +Bimod.AssociatorBimod.hom_right_act_hom' +Bimod.comp_hom' +Bimod.id_hom' +Bimod.LeftUnitorBimod.hom_left_act_hom' +Bimod.LeftUnitorBimod.hom_right_act_hom' +Bimod.RightUnitorBimod.hom_left_act_hom' +Bimod.RightUnitorBimod.hom_right_act_hom' +Bimod.TensorBimod.actRight_one' +Bimod.TensorBimod.left_assoc' +Bimod.TensorBimod.middle_assoc' +Bimod.TensorBimod.one_act_left' +Bimod.TensorBimod.right_assoc' +Bimon_.comp_hom' +Bimon_.id_hom' +birkhoffAverage_congr_ring' +birkhoffAverage_one' +birkhoffAverage_zero' +birkhoffSum_one' +birkhoffSum_succ' +birkhoffSum_zero' +biSup_congr' +biSup_finsetSigma' +biSup_sigma' +BooleanRing.add_eq_zero' +Bool.eq_false_of_not_eq_true' +Bool.eq_true_of_not_eq_false' +Bornology.ext_iff' +Bornology.IsBounded.exists_pos_norm_le' +Bornology.IsBounded.exists_pos_norm_lt' +bound' +BoundedContinuousFunction.const_apply' +BoundedContinuousFunction.dist_le_two_norm' +BoundedContinuousFunction.dist_nonneg' +BoundedContinuousFunction.extend_apply' +BoundedContinuousFunction.instModule' +BoundedContinuousFunction.instSMul' +BoundedLatticeHom.coe_comp_inf_hom' +BoundedLatticeHom.coe_comp_lattice_hom' +BoundedLatticeHom.coe_comp_sup_hom' +BoxIntegral.Box.coe_mk' +BoxIntegral.Box.volume_apply' +BoxIntegral.IntegrationParams.toFilterDistortioniUnion_neBot' +BoxIntegral.Prepartition.iUnion_def' +BoxIntegral.Prepartition.mem_restrict' +BoxIntegral.Prepartition.mem_split_iff' +BoxIntegral.TaggedPrepartition.IsSubordinate.mono' +Bundle.TotalSpace.mk' +calc_eval_z' +card_dvd_exponent_pow_rank' +Cardinal.add_eq_max' +Cardinal.add_le_add' +Cardinal.add_mk_eq_max' +Cardinal.aleph0_le_aleph' +Cardinal.aleph_eq_aleph' +Cardinal.alephIdx_aleph' +Cardinal.cantor' +Cardinal.lift_lt_univ' +Cardinal.lift_mk_shrink' +Cardinal.lift_mk_shrink'' +Cardinal.lt_univ' +Cardinal.mk_eq_two_iff' +Cardinal.mk_finsupp_lift_of_infinite' +Cardinal.mk_finsupp_of_infinite' +Cardinal.mul_comm' +Cardinal.mul_eq_max' +Cardinal.prod_const' +Cardinal.sum_add_distrib' +Cardinal.sum_const' +Cardinal.two_le_iff' +card_le_of_injective' +card_le_of_surjective' +catalan_succ' +CategoryTheory.Abelian.coimageImageComparison_eq_coimageImageComparison' +CategoryTheory.Abelian.epi_of_epi_of_epi_of_mono' +CategoryTheory.Abelian.epi_of_mono_of_epi_of_mono' +CategoryTheory.Abelian.Ext.add_hom' +CategoryTheory.Abelian.Ext.neg_hom' +CategoryTheory.Abelian.FunctorCategory.coimageImageComparison_app' +CategoryTheory.Abelian.mono_of_epi_of_epi_mono' +CategoryTheory.Abelian.mono_of_epi_of_mono_of_mono' +CategoryTheory.Abelian.OfCoimageImageComparisonIsIso.imageMonoFactorisation_e' +CategoryTheory.Abelian.Pseudoelement.pseudoApply_mk' +CategoryTheory.Abelian.Pseudoelement.zero_eq_zero' +CategoryTheory.Abelian.Pseudoelement.zero_morphism_ext' +CategoryTheory.ActionCategory.cases' +CategoryTheory.additive_coyonedaObj' +CategoryTheory.additive_yonedaObj' +CategoryTheory.Adhesive.van_kampen' +CategoryTheory.Adjunction.he'' +CategoryTheory.Arrow.iso_w' +CategoryTheory.BicategoricalCoherence.assoc' +CategoryTheory.BicategoricalCoherence.left' +CategoryTheory.BicategoricalCoherence.right' +CategoryTheory.BicategoricalCoherence.tensorRight' +CategoryTheory.Bifunctor.diagonal' +CategoryTheory.Biproduct.column_nonzero_of_iso' +CategoryTheory.BraidedCategory.yang_baxter' +CategoryTheory.BraidedFunctor.ext' +CategoryTheory.CategoryOfElements.CreatesLimitsAux.π_liftedConeElement' +CategoryTheory.CechNerveTerminalFrom.hasWidePullback' +CategoryTheory.CommSq.HasLift.mk' +CategoryTheory.Comonad.Coalgebra.Hom.ext' +CategoryTheory.ComonadHom.ext' +CategoryTheory.comp_apply' +CategoryTheory.ComposableArrows.Exact.exact' +CategoryTheory.ComposableArrows.IsComplex.zero' +CategoryTheory.ComposableArrows.map'_inv_eq_inv_map' +CategoryTheory.ComposableArrows.naturality' +CategoryTheory.ComposableArrows.Precomp.map_zero_one' +CategoryTheory.composePath_comp' +CategoryTheory.conj_eqToHom_iff_heq' +CategoryTheory.CosimplicialObject.δ_comp_δ' +CategoryTheory.CosimplicialObject.δ_comp_δ'' +CategoryTheory.CosimplicialObject.δ_comp_δ_self' +CategoryTheory.CosimplicialObject.δ_comp_σ_of_gt' +CategoryTheory.CosimplicialObject.δ_comp_σ_self' +CategoryTheory.CosimplicialObject.δ_comp_σ_succ' +CategoryTheory.DifferentialObject.eqToHom_f' +CategoryTheory.e_assoc' +CategoryTheory.Endofunctor.Algebra.Initial.left_inv' +CategoryTheory.eq_of_comp_left_eq' +CategoryTheory.eq_of_comp_right_eq' +CategoryTheory.Equivalence.cancel_counitInv_right_assoc' +CategoryTheory.Equivalence.cancel_unit_right_assoc' +CategoryTheory.ExactPairing.coevaluation_evaluation'' +CategoryTheory.ExactPairing.evaluation_coevaluation'' +CategoryTheory.exists_zigzag' +CategoryTheory.forgetEnrichment_id' +CategoryTheory.Functor.commShiftIso_add' +CategoryTheory.Functor.coreflective' +CategoryTheory.Functor.HasRightDerivedFunctor.mk' +CategoryTheory.Functor.inl_biprodComparison' +CategoryTheory.Functor.inr_biprodComparison' +CategoryTheory.Functor.isContinuous_comp' +CategoryTheory.Functor.IsHomological.mk' +CategoryTheory.Functor.IsLocalization.mk' +CategoryTheory.Functor.Iteration.Hom.ext' +CategoryTheory.Functor.map_comp_heq' +CategoryTheory.Functor.postcomp_map_heq' +CategoryTheory.Functor.reflective' +CategoryTheory.Functor.relativelyRepresentable.map_fst' +CategoryTheory.Functor.relativelyRepresentable.w' +CategoryTheory.Functor.shiftIso_add' +CategoryTheory.Functor.shiftMap_comp' +CategoryTheory.FunctorToTypes.jointly_surjective' +CategoryTheory.FunctorToTypes.prod_ext' +CategoryTheory.Functor.uncurry_obj_curry_obj_flip_flip' +CategoryTheory.Functor.ι_biproductComparison' +CategoryTheory.Grothendieck.comp_fiber' +CategoryTheory.Grothendieck.id_fiber' +CategoryTheory.GrothendieckTopology.OneHypercoverFamily.IsSheafIff.fac' +CategoryTheory.GrothendieckTopology.OneHypercover.mem_sieve₁' +CategoryTheory.GrothendieckTopology.WEqualsLocallyBijective.mk' +CategoryTheory.Grpd.str' +CategoryTheory.HasPullbacksOfInclusions.hasPullbackInr' +CategoryTheory.HasPullbacksOfInclusions.preservesPullbackInl' +CategoryTheory.HasSheafify.mk' +CategoryTheory.Injective.injective_iff_preservesEpimorphisms_preadditive_yoneda_obj' +CategoryTheory.IsCoreflexivePair.mk' +CategoryTheory.IsHomLift.fac' +CategoryTheory.IsHomLift.of_fac' +CategoryTheory.Iso.inv_ext' +CategoryTheory.IsPullback.inl_snd' +CategoryTheory.IsPullback.inr_fst' +CategoryTheory.IsPullback.of_hasBinaryProduct' +CategoryTheory.IsPullback.of_is_bilimit' +CategoryTheory.IsPushout.inl_snd' +CategoryTheory.IsPushout.inr_fst' +CategoryTheory.IsPushout.of_hasBinaryCoproduct' +CategoryTheory.IsPushout.of_is_bilimit' +CategoryTheory.IsReflexivePair.mk' +CategoryTheory.isSheaf_yoneda' +CategoryTheory.LaxBraidedFunctor.ext' +CategoryTheory.Limits.biprod.hom_ext' +CategoryTheory.Limits.biprod.map_eq_map' +CategoryTheory.Limits.biprod.symmetry' +CategoryTheory.Limits.biproduct.hom_ext' +CategoryTheory.Limits.biproduct.map_eq_map' +CategoryTheory.Limits.Cofork.IsColimit.π_desc' +CategoryTheory.Limits.colimit.pre_map' +CategoryTheory.Limits.colimMap_epi' +CategoryTheory.Limits.Concrete.widePullback_ext' +CategoryTheory.Limits.Concrete.widePushout_exists_rep' +CategoryTheory.Limits.coprod.symmetry' +CategoryTheory.Limits.equalizerSubobject_arrow' +CategoryTheory.Limits.Fork.IsLimit.lift_ι' +CategoryTheory.Limits.ImageMap.mk.injEq' +CategoryTheory.Limits.imageSubobject_arrow' +CategoryTheory.Limits.kernelSubobject_arrow' +CategoryTheory.Limits.limit.map_pre' +CategoryTheory.Limits.limLax_obj' +CategoryTheory.Limits.limMap_mono' +CategoryTheory.Limits.MonoCoprod.mk' +CategoryTheory.Limits.MonoCoprod.mono_binaryCofanSum_inl' +CategoryTheory.Limits.MonoCoprod.mono_binaryCofanSum_inr' +CategoryTheory.Limits.MonoCoprod.mono_of_injective' +CategoryTheory.Limits.Multicoequalizer.multicofork_ι_app_right' +CategoryTheory.Limits.Multicofork.ofSigmaCofork_ι_app_right' +CategoryTheory.Limits.parallelPair_initial_mk' +CategoryTheory.Limits.Pi.map'_comp_map' +CategoryTheory.Limits.Pi.map_comp_map' +CategoryTheory.Limits.prod.symmetry' +CategoryTheory.Limits.Sigma.map'_comp_map' +CategoryTheory.Limits.Sigma.map_comp_map' +CategoryTheory.Limits.Sigma.ι_comp_map' +CategoryTheory.Limits.Types.Colimit.w_apply' +CategoryTheory.Limits.Types.Colimit.ι_desc_apply' +CategoryTheory.Limits.Types.Colimit.ι_map_apply' +CategoryTheory.Limits.Types.limit_ext' +CategoryTheory.Limits.Types.limit_ext_iff' +CategoryTheory.Limits.Types.Limit.lift_π_apply' +CategoryTheory.Limits.Types.Limit.map_π_apply' +CategoryTheory.Limits.Types.Limit.w_apply' +CategoryTheory.Limits.Types.Pushout.equivalence_rel' +CategoryTheory.Limits.WalkingParallelPairHom.id.sizeOf_spec' +CategoryTheory.Limits.zero_of_source_iso_zero' +CategoryTheory.Limits.zero_of_target_iso_zero' +CategoryTheory.Localization.Preadditive.comp_add' +CategoryTheory.Localization.Preadditive.zero_add' +CategoryTheory.Localization.SmallShiftedHom.equiv_shift' +CategoryTheory.LocalizerMorphism.guitartExact_of_isRightDerivabilityStructure' +CategoryTheory.LocalizerMorphism.IsLocalizedEquivalence.mk' +CategoryTheory.Mat_.additiveObjIsoBiproduct_naturality' +CategoryTheory.Monad.Algebra.Hom.ext' +CategoryTheory.MonadHom.ext' +CategoryTheory.MonoidalCategory.hom_inv_id_tensor' +CategoryTheory.MonoidalCategory.hom_inv_whiskerRight' +CategoryTheory.MonoidalCategory.inv_hom_id_tensor' +CategoryTheory.MonoidalCategory.inv_hom_whiskerRight' +CategoryTheory.MonoidalCategory.leftUnitor_tensor' +CategoryTheory.MonoidalCategory.leftUnitor_tensor'' +CategoryTheory.MonoidalCategory.leftUnitor_tensor_inv' +CategoryTheory.MonoidalCategory.tensorHom_def' +CategoryTheory.MonoidalCategory.tensor_hom_inv_id' +CategoryTheory.MonoidalCategory.tensor_inv_hom_id' +CategoryTheory.MonoidalCategory.tensorIso_def' +CategoryTheory.MonoidalCategory.whiskerLeft_hom_inv' +CategoryTheory.MonoidalCategory.whiskerLeft_inv_hom' +CategoryTheory.MonoidalCoherence.assoc' +CategoryTheory.MonoidalCoherence.left' +CategoryTheory.MonoidalCoherence.right' +CategoryTheory.MonoidalCoherence.tensor_right' +CategoryTheory.MonoidalNatTrans.ext' +CategoryTheory.MonoOver.mk'_coe' +CategoryTheory.NatIso.naturality_1' +CategoryTheory.NatIso.naturality_2' +CategoryTheory.NatTrans.ext' +CategoryTheory.NatTrans.id_app' +CategoryTheory.NatTrans.vcomp_app' +CategoryTheory.NonPreadditiveAbelian.neg_sub' +CategoryTheory.OplaxNatTrans.Modification.comp_app' +CategoryTheory.OplaxNatTrans.Modification.id_app' +CategoryTheory.Preadditive.epi_iff_surjective' +CategoryTheory.Preadditive.epi_of_isZero_cokernel' +CategoryTheory.Preadditive.mono_iff_injective' +CategoryTheory.Preadditive.mono_of_isZero_kernel' +CategoryTheory.Prefunctor.mapPath_comp' +CategoryTheory.PreOneHypercover.sieve₁_eq_pullback_sieve₁' +CategoryTheory.PreservesPullbacksOfInclusions.preservesPullbackInl' +CategoryTheory.PreservesPullbacksOfInclusions.preservesPullbackInr' +CategoryTheory.Presheaf.isLocallyInjective_toSheafify' +CategoryTheory.Presheaf.isLocallySurjective_iff_imagePresheaf_sheafify_eq_top' +CategoryTheory.Presheaf.isLocallySurjective_toSheafify' +CategoryTheory.Pretriangulated.mem_distTriang_op_iff' +CategoryTheory.Pretriangulated.Opposite.mem_distinguishedTriangles_iff' +CategoryTheory.Projective.projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj' +CategoryTheory.ProjectiveResolution.pOpcycles_comp_fromLeftDerivedZero' +CategoryTheory.Quiv.str' +CategoryTheory.Quotient.lift_unique' +CategoryTheory.RanIsSheafOfIsCocontinuous.fac' +CategoryTheory.RanIsSheafOfIsCocontinuous.liftAux_map' +CategoryTheory.regularTopology.equalizerCondition_w' +CategoryTheory.Sheaf.epi_of_isLocallySurjective' +CategoryTheory.Sheaf.isLocallySurjective_iff_epi' +CategoryTheory.SheafOfTypes.Hom.ext' +CategoryTheory.shift_neg_shift' +CategoryTheory.shift_shift' +CategoryTheory.shift_shift_neg' +CategoryTheory.shiftZero' +CategoryTheory.ShortComplex.abLeftHomologyData_f' +CategoryTheory.ShortComplex.epi_homologyMap_of_epi_cyclesMap' +CategoryTheory.ShortComplex.Exact.desc' +CategoryTheory.ShortComplex.Exact.epi_f' +CategoryTheory.ShortComplex.exact_iff_epi_imageToKernel' +CategoryTheory.ShortComplex.Exact.isIso_f' +CategoryTheory.ShortComplex.Exact.isIso_g' +CategoryTheory.ShortComplex.Exact.lift' +CategoryTheory.ShortComplex.Exact.mono_g' +CategoryTheory.ShortComplex.f'_cyclesMap' +CategoryTheory.ShortComplex.HasHomology.mk' +CategoryTheory.ShortComplex.hasHomology_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.hasHomology_of_isIso_leftRightHomologyComparison' +CategoryTheory.ShortComplex.hasHomology_of_preserves' +CategoryTheory.ShortComplex.HasLeftHomology.mk' +CategoryTheory.ShortComplex.hasLeftHomology_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.hasLeftHomology_of_preserves' +CategoryTheory.ShortComplex.HasRightHomology.mk' +CategoryTheory.ShortComplex.hasRightHomology_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.hasRightHomology_of_preserves' +CategoryTheory.ShortComplex.HomologyData.exact_iff' +CategoryTheory.ShortComplex.HomologyData.map_homologyMap' +CategoryTheory.ShortComplex.isIso₂_of_shortExact_of_isIso₁₃' +CategoryTheory.ShortComplex.isIso_cyclesMap_of_isIso_of_mono' +CategoryTheory.ShortComplex.isIso_homologyMap_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.isIso_leftRightHomologyComparison' +CategoryTheory.ShortComplex.isIso_opcyclesMap_of_isIso_of_epi' +CategoryTheory.ShortComplex.LeftHomologyData.exact_iff_epi_f' +CategoryTheory.ShortComplex.LeftHomologyData.map_cyclesMap' +CategoryTheory.ShortComplex.LeftHomologyData.map_f' +CategoryTheory.ShortComplex.LeftHomologyData.map_leftHomologyMap' +CategoryTheory.ShortComplex.LeftHomologyData.ofEpiOfIsIsoOfMono'_f' +CategoryTheory.ShortComplex.LeftHomologyData.ofIsColimitCokernelCofork_f' +CategoryTheory.ShortComplex.LeftHomologyData.ofIsLimitKernelFork_f' +CategoryTheory.ShortComplex.LeftHomologyData.ofZeros_f' +CategoryTheory.ShortComplex.LeftHomologyData.op_g' +CategoryTheory.ShortComplex.LeftHomologyData.unop_g' +CategoryTheory.ShortComplex.LeftHomologyData.τ₁_ofEpiOfIsIsoOfMono_f' +CategoryTheory.ShortComplex.leftHomologyπ_naturality' +CategoryTheory.ShortComplex.leftRightHomologyComparison'_eq_leftHomologpMap'_comp_iso_hom_comp_rightHomologyMap' +CategoryTheory.ShortComplex.moduleCatLeftHomologyData_f' +CategoryTheory.ShortComplex.mono_homologyMap_of_mono_opcyclesMap' +CategoryTheory.ShortComplex.opcyclesMap'_g' +CategoryTheory.ShortComplex.p_opcyclesMap' +CategoryTheory.ShortComplex.quasiIso_iff_isIso_homologyMap' +CategoryTheory.ShortComplex.quasiIso_iff_isIso_leftHomologyMap' +CategoryTheory.ShortComplex.quasiIso_iff_isIso_rightHomologyMap' +CategoryTheory.ShortComplex.RightHomologyData.exact_iff_mono_g' +CategoryTheory.ShortComplex.RightHomologyData.map_g' +CategoryTheory.ShortComplex.RightHomologyData.map_opcyclesMap' +CategoryTheory.ShortComplex.RightHomologyData.map_rightHomologyMap' +CategoryTheory.ShortComplex.RightHomologyData.ofEpiOfIsIsoOfMono_g' +CategoryTheory.ShortComplex.RightHomologyData.ofIsColimitCokernelCofork_g' +CategoryTheory.ShortComplex.RightHomologyData.ofIsLimitKernelFork_g' +CategoryTheory.ShortComplex.RightHomologyData.ofZeros_g' +CategoryTheory.ShortComplex.RightHomologyData.op_f' +CategoryTheory.ShortComplex.RightHomologyData.p_g' +CategoryTheory.ShortComplex.RightHomologyData.unop_f' +CategoryTheory.ShortComplex.RightHomologyData.ι_g' +CategoryTheory.ShortComplex.rightHomologyι_naturality' +CategoryTheory.ShortComplex.ShortExact.mk' +CategoryTheory.ShortComplex.ShortExact.δ_apply' +CategoryTheory.ShortComplex.ShortExact.δ_eq' +CategoryTheory.SimplicialObject.δ_comp_δ' +CategoryTheory.SimplicialObject.δ_comp_δ'' +CategoryTheory.SimplicialObject.δ_comp_δ_self' +CategoryTheory.SimplicialObject.δ_comp_σ_of_gt' +CategoryTheory.SimplicialObject.δ_comp_σ_self' +CategoryTheory.SimplicialObject.δ_comp_σ_succ' +CategoryTheory.SingleFunctors.shiftIso_add' +CategoryTheory.StrongEpi.mk' +CategoryTheory.StrongMono.mk' +CategoryTheory.Subgroupoid.coe_inv_coe' +CategoryTheory.Subgroupoid.IsNormal.conj' +CategoryTheory.Subobject.inf_eq_map_pullback' +CategoryTheory.Tor'_map_app' +CategoryTheory.Triangulated.Subcategory.ext₁' +CategoryTheory.Triangulated.Subcategory.ext₃' +CategoryTheory.Triangulated.Subcategory.W_iff' +CategoryTheory.Triangulated.Subcategory.W.mk' +CategoryTheory.TwoSquare.GuitartExact.vComp' +CategoryTheory.whiskerLeft_id' +CategoryTheory.whiskerRight_id' +CategoryTheory.yonedaEquiv_naturality' +Cauchy.comap' +CauchyFilter.mem_uniformity' +cauchy_iff' +cauchy_iInf_uniformSpace' +cauchy_map_iff' +Cauchy.mono' +cauchy_pi_iff' +cauchySeq_iff' +CauSeq.bounded' +CauSeq.mul_equiv_zero' +cfc_comp' +cfcₙ_comp' +CharP.exists' +CharP.natCast_eq_natCast' +charP_of_injective_algebraMap' +CharP.pi' +CharP.subring' +ChartedSpaceCore.open_source' +CharTwo.neg_eq' +CharTwo.sub_eq_add' +ciInf_le' +ciInf_le_of_le' +ciInf_subtype' +ciInf_subtype'' +CircleDeg1Lift.tendsto_translation_number' +CircleDeg1Lift.tendsto_translation_number₀' +CircleDeg1Lift.translationNumber_conj_eq' +CircleDeg1Lift.translationNumber_eq_of_tendsto₀' +circleIntegral.norm_integral_le_of_norm_le_const' +circleMap_mem_sphere' +ciSup_le' +ciSup_le_iff' +ciSup_mono' +ciSup_or' +ciSup_subtype' +ciSup_subtype'' +Classical.choose_eq' +CliffordAlgebra.instAlgebra' +CliffordAlgebra.star_def' +ClosedIciTopology.isClosed_ge' +ClosedIicTopology.isClosed_le' +closedUnderRestriction' +closure_smul₀' +clusterPt_iff_lift'_closure' +ClusterPt.of_le_nhds' +cmp_div_one' +cmp_mul_left' +cmp_mul_right' +CochainComplex.HomComplex.Cochain.shift_v' +CochainComplex.mappingCone.d_fst_v' +CochainComplex.mappingCone.d_snd_v' +CochainComplex.shiftFunctorAdd'_hom_app_f' +CochainComplex.shiftFunctorAdd'_inv_app_f' +CochainComplex.shiftFunctor_map_f' +CochainComplex.shiftFunctor_obj_d' +CochainComplex.shiftFunctor_obj_X' +Codisjoint.ne_bot_of_ne_top' +Codisjoint.of_codisjoint_sup_of_le' +Codisjoint.sup_left' +Codisjoint.sup_right' +coe_comp_nnnorm' +coe_nnnorm' +CofiniteTopology.isOpen_iff' +comap_norm_atTop' +comap_norm_nhdsWithin_Ioi_zero' +CommGrp.coe_comp' +CommGrp.coe_id' +CommMon_.comp' +CommMon_.id' +commProb_def' +CommRingCat.equalizer_ι_is_local_ring_hom' +CommRingCat.instCommRing' +CommRingCat.instFunLike' +CommRingCat.instFunLike'' +CommRingCat.instFunLike''' +CommSemiRingCat.instCommSemiring' +Commute.mul_self_sub_mul_self_eq' +Comon_.comp_hom' +Comon_.id_hom' +CompactIccSpace.mk' +CompactIccSpace.mk'' +CompHaus.toProfinite_obj' +compl_beattySeq' +CompleteLattice.Independent.comp' +CompleteLattice.independent_def' +CompleteLattice.independent_def'' +CompleteLattice.independent_of_dfinsupp_sumAddHom_injective' +CompleteLattice.Independent.supIndep' +CompleteLattice.inf_continuous' +CompleteLattice.sSup_continuous' +CompletelyDistribLattice.MinimalAxioms.iInf_iSup_eq' +CompleteOrthogonalIdempotents.bijective_pi' +CompleteSublattice.coe_sInf' +CompleteSublattice.coe_sSup' +Complex.abs_eq_one_iff' +Complex.AbsTheory.abs_nonneg' +Complex.affine_of_mapsTo_ball_of_exists_norm_dslope_eq_div' +Complex.conj_mul' +Complex.cos_eq_tsum' +Complex.cos_sq' +Complex.cos_two_mul' +Complex.cpow_ofNat_mul' +Complex.deriv_cos' +Complex.equivRealProd_apply_le' +Complex.exp_bound' +Complex.hasStrictFDerivAt_cpow' +Complex.hasSum_conj' +Complex.hasSum_cos' +Complex.hasSum_sin' +Complex.mul_conj' +Complex.ofReal_mul' +Complex.rank_real_complex' +Complex.restrictScalars_one_smulRight' +ComplexShape.Embedding.not_boundaryGE_next' +ComplexShape.Embedding.not_boundaryLE_prev' +ComplexShape.next_add' +ComplexShape.next_eq' +ComplexShape.next_eq_self' +ComplexShape.prev_eq' +ComplexShape.prev_eq_self' +Complex.sin_eq_tsum' +Complex.stolzCone_subset_stolzSet_aux' +Complex.tan_add' +Complex.UnitDisc.instSMulCommClass_circle' +Complex.UnitDisc.instSMulCommClass_closedBall' +compl_sInf' +compl_sSup' +CompositionAsSet.lt_length' +Composition.blocks_pos' +Composition.mem_range_embedding_iff' +Composition.one_le_blocks' +Composition.sizeUpTo_succ' +Computability.inhabitedΓ' +ComputablePred.computable_iff_re_compl_re' +Computable.vector_ofFn' +Computation.bind_pure' +Computation.eq_thinkN' +Computation.map_pure' +Computation.map_think' +Computation.results_of_terminates' +ConcaveOn.left_le_of_le_right' +ConcaveOn.left_le_of_le_right'' +ConcaveOn.left_lt_of_lt_right' +ConcaveOn.lt_right_of_left_lt' +ConcaveOn.mul' +ConcaveOn.mul_convexOn' +ConcaveOn.right_le_of_le_left' +ConcaveOn.right_le_of_le_left'' +ConcaveOn.smul' +ConcaveOn.smul'' +ConcaveOn.smul_convexOn' +Concept.ext' +Con.coe_mk' +conformalFactorAt_inner_eq_mul_inner' +CongruenceSubgroup.Gamma1_mem' +CongruenceSubgroup.Gamma_mem' +ConjAct.smulCommClass' +ConjAct.smulCommClass₀' +ConjAct.unitsSMulCommClass' +conjneg_neg' +conjugate_le_conjugate' +conjugate_lt_conjugate' +conjugate_nonneg' +conjugate_pos' +Con.mrange_mk' +ConnectedComponents.coe_eq_coe' +connectedComponents_lift_unique' +ContDiffAt.comp' +contDiffAt_id' +contDiffAt_pi' +contDiffAt_prod' +ContDiff.comp' +contDiff_id' +ContDiff.iterate_deriv' +ContDiffOn.div' +contDiffOn_id' +contDiffOn_pi' +contDiffOn_prod' +contDiff_pi' +contDiff_prod' +ContDiffWithinAt.congr' +ContDiffWithinAt.congr_of_eventually_eq' +ContDiffWithinAt.contDiffOn' +contDiffWithinAt_inter' +contDiffWithinAt_prod' +ContinuousAlgHom.coe_comp' +ContinuousAlgHom.coe_fst' +ContinuousAlgHom.coe_id' +ContinuousAlgHom.coe_mk' +ContinuousAlgHom.coe_prodMap' +ContinuousAlgHom.coe_restrictScalars' +ContinuousAlgHom.coe_snd' +ContinuousAt.comp' +continuousAt_const_cpow' +ContinuousAt.div' +continuousAt_extChartAt' +continuousAt_extChartAt_symm' +continuousAt_extChartAt_symm'' +ContinuousAt.finset_inf' +ContinuousAt.finset_sup' +continuousAt_id' +continuousAt_iff_continuous_left'_right' +ContinuousAt.inf' +continuousAt_jacobiTheta₂' +ContinuousAt.nnnorm' +ContinuousAt.norm' +continuousAt_pi' +ContinuousAt.prod_map' +ContinuousAt.sup' +Continuous.comp' +Continuous.comp_continuousOn' +Continuous.div' +continuous_div_left' +continuous_div_right' +Continuous.finset_inf' +Continuous.finset_sup' +continuous_id' +continuous_if' +Continuous.inf' +ContinuousLinearEquiv.coe_refl' +ContinuousLinearEquiv.comp_hasFDerivAt_iff' +ContinuousLinearEquiv.comp_hasFDerivWithinAt_iff' +ContinuousLinearEquiv.comp_right_hasFDerivAt_iff' +ContinuousLinearEquiv.comp_right_hasFDerivWithinAt_iff' +ContinuousLinearMap.apply_apply' +ContinuousLinearMap.applySMulCommClass' +ContinuousLinearMap.coe_add' +ContinuousLinearMap.coe_comp' +ContinuousLinearMap.coe_flipₗᵢ' +ContinuousLinearMap.coeFn_compLp' +ContinuousLinearMap.coe_fst' +ContinuousLinearMap.coe_id' +ContinuousLinearMap.coe_mk' +ContinuousLinearMap.coe_neg' +ContinuousLinearMap.coe_pi' +ContinuousLinearMap.coe_prodMap' +ContinuousLinearMap.coe_restrictScalars' +ContinuousLinearMap.coe_restrict_scalarsL' +ContinuousLinearMap.coe_smul' +ContinuousLinearMap.coe_snd' +ContinuousLinearMap.coe_sub' +ContinuousLinearMap.coe_sum' +ContinuousLinearMap.coe_zero' +ContinuousLinearMap.compFormalMultilinearSeries_apply' +ContinuousLinearMap.comp_memℒp' +ContinuousLinearMap.integral_comp_comm' +ContinuousLinearMap.measurable_apply' +ContinuousLinearMap.mul_apply' +ContinuousLinearMap.norm_extendTo𝕜' +ContinuousLinearMap.opNorm_le_of_shell' +ContinuousLinearMap.sub_apply' +ContinuousLinearMap.toSpanSingleton_smul' +ContinuousMap.coe_const' +ContinuousMap.coe_inf' +ContinuousMap.coe_sup' +ContinuousMap.comp_yonedaPresheaf' +ContinuousMap.continuous.comp' +ContinuousMap.continuous_const' +ContinuousMap.instSMul' +ContinuousMap.liftCover_coe' +ContinuousMap.liftCover_restrict' +ContinuousMap.module' +ContinuousMap.unitsLift_symm_apply_apply_inv' +ContinuousMapZero.instIsScalarTower' +ContinuousMapZero.instSMulCommClass' +Continuous.matrix_blockDiag' +Continuous.matrix_blockDiagonal' +continuousMultilinearCurryRightEquiv_apply' +continuousMultilinearCurryRightEquiv_symm_apply' +continuous_nnnorm' +Continuous.nnnorm' +continuous_norm' +Continuous.norm' +ContinuousOn.circleIntegrable' +ContinuousOn.comp' +ContinuousOn.comp'' +ContinuousOn.div' +ContinuousOn.finset_inf' +ContinuousOn.finset_sup' +continuousOn_id' +ContinuousOn.if' +continuousOn_iff' +ContinuousOn.inf' +ContinuousOn.nnnorm' +ContinuousOn.norm' +continuousOn_pi' +ContinuousOn.piecewise' +continuousOn_piecewise_ite' +ContinuousOn.sup' +Continuous.quotient_liftOn' +Continuous.quotient_map' +continuous_quotient_mk' +Continuous.strictMono_of_inj_boundedOrder' +Continuous.sup' +ContinuousWithinAt.comp' +ContinuousWithinAt.div' +ContinuousWithinAt.finset_inf' +ContinuousWithinAt.finset_sup' +ContinuousWithinAt.inf' +continuousWithinAt_inter' +ContinuousWithinAt.nnnorm' +ContinuousWithinAt.norm' +ContinuousWithinAt.preimage_mem_nhdsWithin' +ContinuousWithinAt.preimage_mem_nhdsWithin'' +ContinuousWithinAt.sup' +contMDiffAt_extChartAt' +contMDiffAt_finset_prod' +ContMDiffAt.prod_map' +contMDiff_finset_prod' +ContMDiffMap.mdifferentiable' +contMDiffOn_finset_prod' +contMDiffOn_iff_of_mem_maximalAtlas' +ContMDiffSection.mdifferentiable' +contMDiffWithinAt_finset_prod' +contMDiffWithinAt_iff_of_mem_source' +contMDiffWithinAt_inter' +ContractingWith.apriori_edist_iterate_efixedPoint_le' +ContractingWith.edist_efixedPoint_le' +ContractingWith.edist_efixedPoint_lt_top' +ContractingWith.efixedPoint_isFixedPt' +ContractingWith.efixedPoint_mem' +ContractingWith.fixedPoint_unique' +ContractingWith.one_sub_K_pos' +ContractingWith.tendsto_iterate_efixedPoint' +ConvexBody.coe_smul' +Convex.mem_toCone' +ConvexOn.le_left_of_right_le' +ConvexOn.le_left_of_right_le'' +ConvexOn.le_right_of_left_le' +ConvexOn.le_right_of_left_le'' +ConvexOn.lt_left_of_right_lt' +ConvexOn.lt_right_of_left_lt' +ConvexOn.mul' +ConvexOn.mul_concaveOn' +ConvexOn.smul' +ConvexOn.smul'' +ConvexOn.smul_concaveOn' +coord_norm' +CovBy.ne' +CoxeterSystem.alternatingWord_succ' +CoxeterSystem.exists_reduced_word' +CoxeterSystem.length_mul_ge_length_sub_length' +CoxeterSystem.simple_mul_simple_pow' +CPolynomialOn.congr' +CPolynomialOn_congr' +cpow_eq_nhds' +cross_anticomm' +csInf_le' +csInf_le_csInf' +csSup_le' +csSup_le_csSup' +csSup_le_iff' +CStarAlgebra.conjugate_le_norm_smul' +CStarAlgebra.instNonnegSpectrumClass' +CStarRing.conjugate_le_norm_smul' +CStarRing.instNonnegSpectrumClass' +CStarRing.norm_star_mul_self' +Ctop.Realizer.ext' +Cubic.degree_of_a_eq_zero' +Cubic.degree_of_a_ne_zero' +Cubic.degree_of_b_eq_zero' +Cubic.degree_of_b_ne_zero' +Cubic.degree_of_c_eq_zero' +Cubic.degree_of_c_ne_zero' +Cubic.degree_of_d_eq_zero' +Cubic.degree_of_d_ne_zero' +Cubic.leadingCoeff_of_a_ne_zero' +Cubic.leadingCoeff_of_b_ne_zero' +Cubic.leadingCoeff_of_c_eq_zero' +Cubic.leadingCoeff_of_c_ne_zero' +Cubic.monic_of_a_eq_one' +Cubic.monic_of_b_eq_one' +Cubic.monic_of_c_eq_one' +Cubic.monic_of_d_eq_one' +Cubic.natDegree_of_a_eq_zero' +Cubic.natDegree_of_a_ne_zero' +Cubic.natDegree_of_b_eq_zero' +Cubic.natDegree_of_b_ne_zero' +Cubic.natDegree_of_c_eq_zero' +Cubic.natDegree_of_c_ne_zero' +Cubic.of_a_eq_zero' +Cubic.of_b_eq_zero' +Cubic.of_c_eq_zero' +Cubic.of_d_eq_zero' +Cycle.next_reverse_eq_prev' +Cycle.prev_reverse_eq_next' +CyclotomicField.algebra' +dec_em' +Decidable.mul_lt_mul'' +Decidable.Partrec.const' +decide_False' +decide_True' +DedekindDomain.ProdAdicCompletions.algebra' +DedekindDomain.ProdAdicCompletions.algebraMap_apply' +DedekindDomain.ProdAdicCompletions.IsFiniteAdele.algebraMap' +DenseEmbedding.mk' +Dense.exists_ge' +Dense.exists_le' +DenseInducing.extend_eq_at' +DenseInducing.mk' +Denumerable.lower_raise' +Denumerable.raise_lower' +deriv_add_const' +Derivation.apply_aeval_eq' +Derivation.coe_mk' +deriv_const' +deriv_const_add' +deriv_const_mul_field' +deriv_id' +deriv_id'' +deriv_inv' +deriv_inv'' +deriv_mul_const_field' +deriv.neg' +deriv_neg' +deriv_neg'' +deriv_pow' +deriv_pow'' +deriv_sqrt_mul_log' +deriv.star' +derivWithin_congr_set' +derivWithin_inv' +derivWithin_pow' +deriv_zpow' +det_traceMatrix_ne_zero' +DFinsupp.coe_mk' +DFinsupp.filter_ne_eq_erase' +DFinsupp.le_iff' +DFinsupp.Lex.wellFounded' +DFinsupp.wellFoundedLT' +DFunLike.ext' +DiffContOnCl.differentiableAt' +Diffeomorph.symm_trans' +DifferentiableAt.comp' +differentiableAt_id' +differentiableAt_inv' +DifferentiableAt.inv' +differentiableAt_pi'' +Differentiable.comp' +differentiable_id' +Differentiable.inv' +DifferentiableOn.comp' +differentiableOn_id' +differentiableOn_inv' +DifferentiableOn.inv' +differentiableOn_pi'' +differentiable_pi'' +DifferentiableWithinAt.comp' +differentiableWithinAt_congr_set' +differentiableWithinAt_inter' +differentiableWithinAt_inv' +DifferentiableWithinAt.inv' +differentiableWithinAt_pi'' +DirectedOn.mono' +directedOn_pair' +DirectSum.Gmodule.mul_smul' +DirectSum.Gmodule.one_smul' +DirichletCharacter.level_one' +DirichletCharacter.toUnitHom_eq_char' +discreteTopology_iff_orderTopology_of_pred_succ' +DiscreteTopology.of_forall_le_norm' +DiscreteTopology.orderTopology_of_pred_succ' +DiscreteValuationRing.addVal_def' +Disjoint.inf_left' +Disjoint.inf_right' +Disjoint.inter_left' +Disjoint.inter_right' +Disjoint.of_disjoint_inf_of_le' +dist_eq_norm_div' +dist_le_norm_add_norm' +dist_midpoint_midpoint_le' +dist_norm_norm_le' +dist_partial_sum' +dist_pi_le_iff' +DistribMulActionHom.coe_fn_coe' +dite_eq_iff' +div_add' +div_div_cancel' +div_div_cancel_left' +div_div_div_cancel_left' +div_div_self' +div_eq_iff_eq_mul' +div_eq_of_eq_mul' +div_eq_of_eq_mul'' +div_le_div'' +div_le_div_iff' +div_le_div_left' +div_le_div_right' +div_left_inj' +div_le_iff₀' +div_le_iff_le_mul' +div_le_iff_of_neg' +div_le_one' +div_lt_div' +div_lt_div'' +div_lt_div_iff' +div_lt_div_left' +div_lt_div_right' +div_lt_iff' +div_lt_iff_lt_mul' +div_lt_iff_of_neg' +div_lt_one' +div_mul_div_cancel' +div_mul_div_cancel₀' +div_self' +div_self_mul_self' +div_sub' +Doset.disjoint_out' +Doset.out_eq' +DoubleCentralizer.nnnorm_def' +DoubleCentralizer.norm_def' +dvd_antisymm' +dvd_geom_sum₂_iff_of_dvd_sub' +edist_eq_coe_nnnorm' +EllipticCurve.coe_inv_map_Δ' +EllipticCurve.coe_inv_variableChange_Δ' +EllipticCurve.coe_map_Δ' +EllipticCurve.coe_variableChange_Δ' +em' +Embedding.mk' +EMetric.diam_pos_iff' +EMetric.diam_union' +EMetric.mem_ball' +EMetric.mem_closedBall' +EMetric.totallyBounded_iff' +ENat.sSup_eq_zero' +Encodable.mem_decode₂' +ENNReal.add_biSup' +ENNReal.biSup_add' +ENNReal.biSup_add_biSup_le' +ENNReal.div_le_iff' +ENNReal.div_le_of_le_mul' +ENNReal.div_lt_of_lt_mul' +ENNReal.exists_frequently_lt_of_liminf_ne_top' +ENNReal.exists_pos_sum_of_countable' +ENNReal.iInf_mul_left' +ENNReal.iInf_mul_right' +ENNReal.inv_le_inv' +ENNReal.inv_lt_inv' +ENNReal.log_pos_real' +ENNReal.mul_div_cancel' +ENNReal.mul_le_of_le_div' +ENNReal.mul_lt_mul_left' +ENNReal.mul_lt_mul_right' +ENNReal.mul_lt_of_lt_div' +ENNReal.mul_top' +ENNReal.nhds_top' +ENNReal.ofReal_le_ofReal_iff' +ENNReal.ofReal_lt_ofReal_iff' +ENNReal.ofReal_mul' +ENNReal.range_coe' +ENNReal.some_eq_coe' +ENNReal.toNNReal_eq_toNNReal_iff' +ENNReal.top_mul' +ENNReal.toReal_eq_toReal_iff' +ENNReal.toReal_mono' +ENNReal.toReal_ofReal' +ENNReal.tsum_eq_iSup_nat' +ENNReal.tsum_eq_iSup_sum' +ENNReal.tsum_prod' +ENNReal.tsum_sigma' +Eq.cmp_eq_eq' +eq_div_iff_mul_eq' +eq_div_iff_mul_eq'' +eq_div_of_mul_eq' +eq_div_of_mul_eq'' +eq_intCast' +eq_mul_of_div_eq' +eq_natCast' +eq_of_forall_dvd' +eq_of_prime_pow_eq' +eqOn_closure₂' +eq_one_of_inv_eq' +eq_one_of_mul_left' +eq_one_of_mul_right' +eqRec_heq' +Equiv.bijOn' +Equiv.coe_piCongr' +Equiv.exists_congr' +Equiv.existsUnique_congr' +Equiv.forall₂_congr' +Equiv.forall₃_congr' +Equiv.forall_congr' +Equiv.inhabited' +Equiv.lawfulFunctor' +Equiv.left_inv' +Equiv.Perm.cycleType_eq' +Equiv.Perm.exists_fixed_point_of_prime' +Equiv.Perm.isCycle_of_prime_order' +Equiv.Perm.isCycle_of_prime_order'' +Equiv.Perm.IsCycleOn.exists_pow_eq' +Equiv.Perm.IsCycle.pow_eq_one_iff' +Equiv.Perm.IsCycle.pow_eq_one_iff'' +Equiv.Perm.mem_support_cycleOf_iff' +Equiv.Perm.prod_comp' +Equiv.Perm.SameCycle.exists_pow_eq' +Equiv.Perm.SameCycle.exists_pow_eq'' +Equiv.Perm.signAux_swap_zero_one' +Equiv.Perm.sign_of_cycleType' +Equiv.Perm.sign_swap' +Equiv.right_inv' +EReal.add_lt_add_of_lt_of_le' +EReal.coe_neg' +EReal.nhds_bot' +EReal.nhds_top' +EReal.sign_mul_inv_abs' +essInf_const' +essSup_const' +essSup_mono_measure' +estimator' +EuclideanDomain.div_add_mod' +EuclideanDomain.mod_add_div' +EuclideanDomain.mul_div_cancel' +EuclideanGeometry.center_eq_inversion' +EuclideanGeometry.dist_center_eq_dist_center_of_mem_sphere' +EuclideanGeometry.inversion_dist_center' +EuclideanGeometry.inversion_eq_center' +EuclideanGeometry.mem_sphere' +EuclideanGeometry.Sphere.mem_coe' +eventually_cobounded_le_norm' +exists_apply_eq_apply' +exists_apply_eq_apply2' +exists_apply_eq_apply3' +exists_associated_pow_of_mul_eq_pow' +exists_Ico_subset_of_mem_nhds' +exists_increasing_or_nonincreasing_subseq' +exists_Ioc_subset_of_mem_nhds' +exists_lt_of_lt_ciSup' +exists_lt_of_lt_csSup' +exists_maximal_independent' +exists_one_lt' +exists_one_lt_mul_of_lt' +exists_reduced_fraction' +exists_seq_strictAnti_tendsto' +exists_seq_strictMono_tendsto' +exists_square_le' +exists_sum_eq_one_iff_pairwise_coprime' +exists_unique_eq' +existsUnique_zpow_near_of_one_lt' +extChartAt_preimage_mem_nhds' +extChartAt_source_mem_nhds' +extChartAt_source_mem_nhdsWithin' +extChartAt_target_mem_nhdsWithin' +ext_nat' +fderiv_continuousLinearEquiv_comp' +fderiv_id' +fderiv_list_prod' +fderiv_mul' +fderiv_mul_const' +fderivWithin_congr' +fderivWithin_congr_set' +fderivWithin_eventually_congr_set' +fderivWithin_id' +fderivWithin_list_prod' +fderivWithin_mul' +fderivWithin_mul_const' +FDRep.char_tensor' +FermatLastTheoremWith.fermatLastTheoremWith' +FiberBundleCore.open_source' +Field.finInsepDegree_def' +Field.primitive_element_iff_algHom_eq_of_eval' +Filter.atBot_basis' +Filter.atBot_basis_Iio' +Filter.atTop_basis' +Filter.atTop_basis_Ioi' +Filter.bliminf_congr' +Filter.blimsup_congr' +Filter.comap_eq_lift' +Filter.comap_eval_neBot_iff' +Filter.comap_id' +Filter.const_eventuallyEq' +Filter.coprodᵢ_bot' +Filter.coprodᵢ_eq_bot_iff' +Filter.coprodᵢ_neBot_iff' +Filter.countable_biInf_eq_iInf_seq' +Filter.disjoint_comap_iff_map' +Filter.eventually_atBot_prod_self' +Filter.eventually_atTop_prod_self' +Filter.eventuallyConst_pred' +Filter.eventuallyConst_set' +Filter.EventuallyEq.fderivWithin' +Filter.EventuallyEq.iteratedFDerivWithin' +Filter.EventuallyLE.mul_le_mul' +Filter.eventually_smallSets' +Filter.exists_forall_mem_of_hasBasis_mem_blimsup' +Filter.ext' +Filter.extraction_forall_of_eventually' +Filter.extraction_of_frequently_atTop' +Filter.frequently_atBot' +Filter.frequently_atTop' +Filter.Germ.coe_compTendsto' +Filter.Germ.coe_smul' +Filter.Germ.const_compTendsto' +Filter.Germ.instDistribMulAction' +Filter.Germ.instModule' +Filter.Germ.instMulAction' +Filter.Germ.instSMul' +Filter.hasBasis_biInf_of_directed' +Filter.hasBasis_biInf_principal' +Filter.HasBasis.cauchySeq_iff' +Filter.hasBasis_cobounded_norm' +Filter.HasBasis.cobounded_of_norm' +Filter.HasBasis.eventuallyConst_iff' +Filter.hasBasis_iInf' +Filter.hasBasis_iInf_of_directed' +Filter.HasBasis.inf' +Filter.HasBasis.lift' +Filter.HasBasis.nhds' +Filter.HasBasis.prod_nhds' +Filter.HasBasis.sup' +Filter.HasBasis.to_hasBasis' +Filter.HasBasis.to_image_id' +Filter.HasBasis.uniformEmbedding_iff' +Filter.iInf_neBot_iff_of_directed' +Filter.iInf_sets_eq_finite' +Filter.isScalarTower' +Filter.isScalarTower'' +Filter.le_lift' +Filter.le_limsup_of_frequently_le' +Filter.le_pure_iff' +Filter.lift_lift'_same_eq_lift' +Filter.lift_lift'_same_le_lift' +Filter.lift'_mono' +Filter.lift_mono' +Filter.liminf_eq_iSup_iInf_of_nat' +Filter.liminf_le_of_frequently_le' +Filter.limsup_eq_iInf_iSup_of_nat' +Filter.map_id' +Filter.map_inf' +Filter.map_inv' +Filter.map_one' +Filter.map_prod_eq_map₂' +Filter.mem_bind' +Filter.mem_coclosed_compact' +Filter.mem_cocompact' +Filter.mem_comap' +Filter.mem_comap'' +Filter.mem_iInf' +Filter.mem_iInf_finite' +Filter.mem_inf_principal' +Filter.mem_lift' +Filter.mem_map' +Filter.mem_nhds_iff' +Filter.mem_pi' +Filter.mem_rcomap' +Filter.mono_bliminf' +Filter.mono_blimsup' +Filter.monotone_lift' +Filter.neBot_inf_comap_iff_map' +Filter.nhds_eq' +Filter.principal_le_lift' +Filter.prod_comm' +Filter.prod_lift'_lift' +Filter.prod_map_map_eq' +Filter.ptendsto_of_ptendsto' +Filter.push_pull' +Filter.rcomap'_rcomap' +Filter.sInf_neBot_of_directed' +Filter.smulCommClass_filter' +Filter.smulCommClass_filter'' +Filter.tendsto_atBot' +Filter.tendsto_atBot_add_left_of_ge' +Filter.tendsto_atBot_add_nonpos_left' +Filter.tendsto_atBot_add_nonpos_right' +Filter.tendsto_atBot_add_right_of_ge' +Filter.tendsto_atBot_mono' +Filter.tendsto_atBot_of_add_bdd_below_left' +Filter.tendsto_atBot_of_add_bdd_below_right' +Filter.tendsto_atTop' +Filter.tendsto_atTop_add_left_of_le' +Filter.tendsto_atTop_add_nonneg_left' +Filter.tendsto_atTop_add_nonneg_right' +Filter.tendsto_atTop_add_right_of_le' +Filter.tendsto_atTop_mono' +Filter.tendsto_atTop_of_add_bdd_above_left' +Filter.tendsto_atTop_of_add_bdd_above_right' +Filter.tendsto_congr' +Filter.Tendsto.congr' +Filter.Tendsto.const_div' +Filter.Tendsto.div' +Filter.Tendsto.div_const' +Filter.Tendsto.eventually_ne_atTop' +Filter.tendsto_id' +Filter.Tendsto.if' +Filter.tendsto_iff_rtendsto' +Filter.tendsto_iInf' +Filter.Tendsto.inf_nhds' +Filter.tendsto_inv₀_cobounded' +Filter.tendsto_lift' +Filter.Tendsto.nnnorm' +Filter.Tendsto.norm' +Filter.tendsto_prod_iff' +Filter.Tendsto.sup_nhds' +Filter.unbounded_of_tendsto_atBot' +Filter.unbounded_of_tendsto_atTop' +Filter.univ_mem' +Fin.card_filter_univ_succ' +Fin.castPred_zero' +Fin.cycleRange_zero' +Fin.exists_fin_succ' +Fin.find_min' +Fin.forall_fin_succ' +Fin.insertNth_last' +Fin.insertNth_zero' +Fin.isEmpty' +FiniteDimensional.finiteDimensional_pi' +FiniteField.card' +Finite.Set.finite_biUnion' +Fin.last_pos' +Finmap.ext_iff' +Fin.mem_piFinset_succ' +Fin.mul_one' +Fin.mul_zero' +Fin.one_mul' +Fin.one_pos' +Fin.orderIso_subsingleton' +Fin.partialProd_succ' +Finpartition.IsEquipartition.card_biUnion_offDiag_le' +Finpartition.IsEquipartition.sum_nonUniforms_lt' +Fin.pred_one' +Fin.preimage_apply_01_prod' +Fin.prod_congr' +finprod_emb_domain' +finprod_mem_inter_mul_diff' +finprod_mem_inter_mulSupport_eq' +Fin.prod_univ_get' +Fin.prod_univ_two' +finrank_real_complex_fact' +finRotate_last' +Finset.abs_sum_of_nonneg' +Finset.aemeasurable_prod' +Finset.aestronglyMeasurable_prod' +Finset.card_le_card_of_forall_subsingleton' +Finset.card_mul_le_card_mul' +Finset.coe_inf' +Finset.coe_max' +Finset.coe_min' +Finset.coe_sup' +Finset.Colex.toColex_sdiff_le_toColex_sdiff' +Finset.Colex.toColex_sdiff_lt_toColex_sdiff' +Finset.decidableMem' +Finset.disjoint_filter_filter' +Finset.eq_of_mem_uIcc_of_mem_uIcc' +Finset.eq_prod_range_div' +Finset.erase_injOn' +Finset.exists_le_of_prod_le' +Finset.exists_lt_of_prod_lt' +Finset.exists_mem_eq_inf' +Finset.exists_mem_eq_sup' +Finset.exists_one_lt_of_prod_one_of_exists_ne_one' +Finset.expect_boole_mul' +Finset.expect_dite_eq' +Finset.expect_ite_eq' +Finset.extract_gcd' +Finset.filter_attach' +Finset.filter_inj' +Finset.filter_ne' +Finset.forall_mem_not_eq' +Finset.Icc_mul_Icc_subset' +Finset.Icc_mul_Ico_subset' +Finset.Icc_subset_uIcc' +Finset.Ici_mul_Ici_subset' +Finset.Ici_mul_Ioi_subset' +Finset.Ico_mul_Icc_subset' +Finset.Ico_mul_Ioc_subset' +Finset.Ico_union_Ico' +Finset.Iic_mul_Iic_subset' +Finset.Iic_mul_Iio_subset' +Finset.Iio_mul_Iic_subset' +Finset.image₂_singleton_left' +Finset.image_id' +Finset.image_mul_left' +Finset.image_mul_right' +Finset.inf'_sup_inf' +Finset.insert_inj_on' +Finset.insert_sdiff_insert' +Finset.insert_val' +Finset.Ioc_mul_Ico_subset' +Finset.Ioi_mul_Ici_subset' +Finset.isGreatest_max' +Finset.isLeast_min' +Finset.isScalarTower' +Finset.isScalarTower'' +Finset.le_inf' +Finset.le_max' +Finset.le_min' +Finset.le_sum_condensed' +Finset.le_sum_schlomilch' +Finset.le_sup' +Finset.lt_max'_of_mem_erase_max' +Finset.map_filter' +Finset.max'_eq_sup' +Finset.measurable_prod' +Finset.measurable_range_sup' +Finset.measurable_range_sup'' +Finset.measurable_sup' +Finset.mem_finsuppAntidiag' +Finset.mem_inv' +Finset.mem_map' +Finset.mem_range_iff_mem_finset_range_of_mod_eq' +Finset.mem_uIcc' +Finset.min'_eq_inf' +Finset.min'_lt_max' +Finset.min'_lt_of_mem_erase_min' +Finset.mulEnergy_eq_sum_sq' +Finset.Nat.antidiagonal_eq_image' +Finset.Nat.antidiagonal_eq_map' +Finset.Nat.antidiagonal_succ' +Finset.Nat.antidiagonal_succ_succ' +Finset.Nat.prod_antidiagonal_succ' +Finset.Nat.sum_antidiagonal_succ' +Finset.nnnorm_prod_le' +Finset.noncommProd_cons' +Finset.noncommProd_insert_of_not_mem' +Finset.Nonempty.csInf_eq_min' +Finset.Nonempty.csSup_eq_max' +Finset.norm_prod_le' +Finset.nsmul_inf' +Finset.nsmul_sup' +Finset.ofDual_inf' +Finset.ofDual_max' +Finset.ofDual_min' +Finset.ofDual_sup' +Finset.one_le_prod' +Finset.one_le_prod'' +Finset.one_lt_prod' +Finset.pairwise_cons' +Finset.pairwise_subtype_iff_pairwise_finset' +Finset.piecewise_le_piecewise' +Finset.piecewise_mem_Icc' +Finset.PiFinsetCoe.canLift' +Finset.preimage_mul_left_one' +Finset.preimage_mul_right_one' +Finset.prod_dite_eq' +Finset.prod_eq_one_iff' +Finset.prod_eq_one_iff_of_le_one' +Finset.prod_eq_one_iff_of_one_le' +Finset.prod_fiberwise' +Finset.prod_fiberwise_eq_prod_filter' +Finset.prod_fiberwise_le_prod_of_one_le_prod_fiber' +Finset.prod_fiberwise_of_maps_to' +Finset.prod_finset_product' +Finset.prod_finset_product_right' +Finset.prod_Ico_add' +Finset.prod_image' +Finset.prod_le_one' +Finset.prod_le_prod_fiberwise_of_prod_fiber_le_one' +Finset.prod_le_prod_of_ne_one' +Finset.prod_le_prod_of_subset' +Finset.prod_le_prod_of_subset_of_one_le' +Finset.prod_le_univ_prod_of_one_le' +Finset.prod_lt_one' +Finset.prod_lt_prod' +Finset.prod_lt_prod_of_subset' +Finset.prod_mono_set' +Finset.prod_mono_set_of_one_le' +Finset.prod_pi_mulSingle' +Finset.prod_preimage' +Finset.prod_range_div' +Finset.prod_range_succ' +Finset.prod_sigma' +Finset.range_add_one' +Finset.sdiff_sdiff_left' +Finset.single_le_prod' +Finset.single_lt_prod' +Finset.smulCommClass_finset' +Finset.smulCommClass_finset'' +Finset.smul_prod' +Finset.smul_univ₀' +Finset.sorted_last_eq_max' +Finset.sorted_zero_eq_min' +Finset.stronglyMeasurable_prod' +Finset.subset_singleton_iff' +Finset.sum_apply' +Finset.sum_condensed_le' +Finset.sum_pow' +Finset.sum_schlomilch_le' +Finset.sup'_inf_sup' +Finset.sup_singleton' +Finset.sup_singleton'' +Finset.toDual_inf' +Finset.toDual_max' +Finset.toDual_min' +Finset.toDual_sup' +Finset.tprod_subtype' +Finset.uIcc_subset_uIcc_iff_le' +Finset.untrop_sum' +Fin.size_positive' +Fin.succ_zero_eq_one' +Finsupp.apply_single' +Finsupp.card_support_eq_one' +Finsupp.card_support_le_one' +Finsupp.equivMapDomain_refl' +Finsupp.equivMapDomain_trans' +Finsupp.ext_iff' +Finsupp.le_iff' +Finsupp.le_weight_of_ne_zero' +Finsupp.Lex.wellFounded' +Finsupp.mapDomain_apply' +Finsupp.mapRange_add' +Finsupp.mapRange_neg' +Finsupp.mapRange_sub' +Finsupp.mem_supported' +Finsupp.mulHom_ext' +Finsupp.smul_single' +Finsupp.subtypeDomain_eq_zero_iff' +Finsupp.sum_apply' +Finsupp.sum_cons' +Finsupp.sum_ite_self_eq' +Finsupp.sum_smul_index' +Finsupp.sum_smul_index_linearMap' +Finsupp.sum_sum_index' +Finsupp.support_eq_singleton' +Finsupp.support_subset_singleton' +Finsupp.univ_sum_single_apply' +Finsupp.wellFoundedLT' +Fintype.card_congr' +Fintype.card_of_finset' +Fintype.card_subtype_eq' +Fintype.expect_dite_eq' +Fintype.expect_ite_eq' +Fintype.prod_fiberwise' +Fintype.prod_mono' +Fintype.prod_strictMono' +Fin.univ_image_get' +Fin.univ_image_getElem' +Fin.val_one' +Fin.val_one'' +Fin.zero_mul' +Fin.zero_ne_one' +FirstOrder.Language.addEmptyConstants_is_expansion_on' +FirstOrder.Language.DirectLimit.cg' +FirstOrder.Language.DirectLimit.funMap_quotient_mk'_sigma_mk' +FirstOrder.Language.DirectLimit.lift_quotient_mk'_sigma_mk' +FirstOrder.Language.DirectLimit.relMap_quotient_mk'_sigma_mk' +FirstOrder.Language.Embedding.codRestrict_apply' +FirstOrder.Language.funMap_quotient_mk' +FirstOrder.Language.relMap_quotient_mk' +FirstOrder.Language.Term.realize_quotient_mk' +FixedPoints.minpoly.eval₂' +FixedPoints.smulCommClass' +forall_apply_eq_imp_iff' +forall_eq_apply_imp_iff' +forall_lt_iff_le' +forall_prop_congr' +forall_true_iff' +FormalMultilinearSeries.apply_order_ne_zero' +FormalMultilinearSeries.comp_coeff_zero' +FormalMultilinearSeries.order_eq_find' +FormalMultilinearSeries.order_eq_zero_iff' +fourier_add' +fourier_coe_apply' +fourierIntegral_gaussian_innerProductSpace' +fourierIntegral_gaussian_pi' +fourier_neg' +fourier_zero' +four_ne_zero' +FP.Float.sign' +FractionalIdeal.absNorm_eq' +FractionalIdeal.coeIdeal_eq_zero' +FractionalIdeal.coeIdeal_inj' +FractionalIdeal.coeIdeal_injective' +FractionalIdeal.coeIdeal_le_coeIdeal' +FractionalIdeal.coeIdeal_ne_zero' +FractionalIdeal.inv_zero' +FreeAbelianGroup.induction_on' +FreeAbelianGroup.lift.add' +FreeAbelianGroup.lift_neg' +FreeGroup.map.id' +FreeMagma.lift_comp_of' +FreeMagma.map_mul' +FreeMagma.traverse_mul' +FreeMagma.traverse_pure' +FreeMonoid.countP_of' +FreeSemigroup.lift_comp_of' +FreeSemigroup.map_mul' +FreeSemigroup.traverse_mul' +FreeSemigroup.traverse_pure' +frontier_closedBall' +frontier_Ici' +frontier_Iic' +frontier_Iio' +frontier_Ioi' +frontier_sphere' +Function.Antiperiodic.funext' +Function.Antiperiodic.mul_const' +Function.Antiperiodic.sub_eq' +Function.Bijective.of_comp_iff' +Function.Commute.iterate_pos_le_iff_map_le' +Function.Commute.iterate_pos_lt_iff_map_lt' +Function.Commute.iterate_pos_lt_of_map_lt' +Function.Exact.of_ladder_addEquiv_of_exact' +Function.Exact.split_tfae' +Function.extend_apply' +FunctionField.InftyValuation.map_add_le_max' +FunctionField.InftyValuation.map_mul' +FunctionField.InftyValuation.map_one' +FunctionField.InftyValuation.map_zero' +Function.Injective.eq_iff' +Function.Injective.ne_iff' +Function.Injective.of_comp_iff' +Function.Injective.surjective_comp_right' +Function.iterate_succ' +Function.iterate_succ_apply' +Function.minimalPeriod_iterate_eq_div_gcd' +Function.mulSupport_add_one' +Function.mulSupport_curry' +Function.mulSupport_inv' +Function.mulSupport_one' +Function.mulSupport_one_add' +Function.mulSupport_one_sub' +Function.mulSupport_prod_mk' +Function.mulSupport_subset_iff' +Function.Periodic.mul_const' +Function.periodicOrbit_chain' +Function.Periodic.sub_eq' +Function.support_div' +Function.support_inv' +Function.support_mul' +Function.support_pow' +Function.Surjective.of_comp_iff' +Function.update_comp_eq_of_forall_ne' +Function.update_comp_eq_of_injective' +Function.update_comp_eq_of_not_mem_range' +GaloisCoinsertion.isCoatom_iff' +GaloisConnection.l_csSup' +GaloisConnection.l_u_l_eq_l' +GaloisConnection.u_csInf' +GaloisConnection.u_l_u_eq_u' +GaloisInsertion.isAtom_iff' +gauge_gaugeRescale' +gauge_lt_eq' +gauge_zero' +GaussianFourier.norm_cexp_neg_mul_sq_add_mul_I' +GaussianInt.toComplex_def' +gcd_assoc' +gcd_comm' +gcd_mul_left' +gcd_mul_right' +gcd_neg' +gcd_one_left' +gcd_one_right' +gcd_zero_left' +gcd_zero_right' +GenContFract.of_convs_eq_convs' +ge_of_tendsto' +geom_sum_Ico' +geom_sum_pos' +geom_sum_succ' +GradedTensorProduct.algebraMap_def' +gradient_const' +gradient_eq_deriv' +gramSchmidt_def' +gramSchmidt_def'' +gramSchmidtNormed_unit_length' +gramSchmidtOrthonormalBasis_inv_triangular' +Group.conjugatesOfSet_subset' +Group.fg_iff' +GroupTopology.ext' +Grp.coe_comp' +Grp.coe_id' +Grp.SurjectiveOfEpiAuxs.h_apply_fromCoset' +Grp.SurjectiveOfEpiAuxs.τ_apply_fromCoset' +HahnModule.mul_smul' +HahnModule.one_smul' +HahnModule.support_smul_subset_vadd_support' +HahnModule.zero_smul' +HahnSeries.add_coeff' +HahnSeries.algebraMap_apply' +HahnSeries.mul_assoc' +HahnSeries.mul_coeff_left' +HahnSeries.mul_coeff_right' +HahnSeries.neg_coeff' +HahnSeries.sub_coeff' +HasCompactMulSupport.intro' +HasCompactMulSupport.inv' +HasCompactMulSupport.mono' +HasDerivAt.complexToReal_fderiv' +hasDerivAt_exp_smul_const' +hasDerivAt_exp_smul_const_of_mem_ball' +HasDerivAtFilter.hasGradientAtFilter' +HasDerivAt.hasGradientAt' +hasDerivAt_id' +hasDerivAt_neg' +HasDerivWithinAt.complexToReal_fderiv' +hasDerivWithinAt_congr_set' +hasDerivWithinAt_iff_tendsto_slope' +hasDerivWithinAt_inter' +HasDerivWithinAt.limsup_slope_le' +hasFDerivAt_exp_smul_const' +hasFDerivAt_exp_smul_const_of_mem_ball' +hasFDerivAtFilter_pi' +hasFDerivAt_list_prod' +hasFDerivAt_list_prod_attach' +hasFDerivAt_list_prod_finRange' +HasFDerivAt.mul' +HasFDerivAt.mul_const' +hasFDerivAt_pi' +hasFDerivAt_pi'' +HasFDerivWithinAt.congr' +hasFDerivWithinAt_congr_set' +hasFDerivWithinAt_inter' +HasFDerivWithinAt.list_prod' +HasFDerivWithinAt.mul' +HasFDerivWithinAt.mul_const' +hasFDerivWithinAt_pi' +hasFDerivWithinAt_pi'' +HasFiniteFPowerSeriesOnBall.mk' +hasFPowerSeriesAt_iff' +HasFPowerSeriesOnBall.factorial_smul' +hasFTaylorSeriesUpToOn_pi' +HasFTaylorSeriesUpToOn.zero_eq' +HasFTaylorSeriesUpTo.zero_eq' +HasGradientAtFilter.hasDerivAtFilter' +HasGradientAt.hasDerivAt' +hasGradientWithinAt_congr_set' +HasLineDerivWithinAt.congr' +HasLineDerivWithinAt.hasLineDerivAt' +HasMFDerivAt.mul' +hasMFDerivWithinAt_inter' +HasMFDerivWithinAt.mul' +HasOrthogonalProjection.map_linearIsometryEquiv' +hasProd_nat_add_iff' +HasStrictDerivAt.complexToReal_fderiv' +hasStrictDerivAt_exp_smul_const' +hasStrictDerivAt_exp_smul_const_of_mem_ball' +hasStrictFDerivAt_exp_smul_const' +hasStrictFDerivAt_exp_smul_const_of_mem_ball' +hasStrictFDerivAt_list_prod' +HasStrictFDerivAt.list_prod' +hasStrictFDerivAt_list_prod_attach' +hasStrictFDerivAt_list_prod_finRange' +HasStrictFDerivAt.mul' +HasStrictFDerivAt.mul_const' +hasStrictFDerivAt_pi' +hasStrictFDerivAt_pi'' +hasSum_choose_mul_geometric_of_norm_lt_one' +hasSum_geometric_two' +HasSum.matrix_blockDiag' +HasSum.matrix_blockDiagonal' +hasSum_sum_range_mul_of_summable_norm' +Homeomorph.comp_continuousAt_iff' +Homeomorph.comp_continuous_iff' +Homeomorph.comp_isOpenMap_iff' +HomogeneousIdeal.ext' +HomologicalComplex₂.d₁_eq' +HomologicalComplex₂.d₁_eq_zero' +HomologicalComplex₂.d₂_eq' +HomologicalComplex₂.d₂_eq_zero' +HomologicalComplex₂.totalAux.d₁_eq' +HomologicalComplex₂.totalAux.d₂_eq' +HomologicalComplex.exactAt_iff' +HomologicalComplex.extend.d_none_eq_zero' +HomologicalComplex.homotopyCofiber.desc_f' +HomologicalComplex.homotopyCofiber.ext_from_X' +HomologicalComplex.homotopyCofiber.ext_to_X' +HomologicalComplex.homotopyCofiber.inlX_d' +HomologicalComplex.isZero_extend_X' +HomologicalComplex.mapBifunctor.d₁_eq' +HomologicalComplex.mapBifunctor.d₁_eq_zero' +HomologicalComplex.mapBifunctor.d₂_eq' +HomologicalComplex.mapBifunctor.d₂_eq_zero' +HomologicalComplex.restrictionMap_f' +HomotopyCategory.Pretriangulated.invRotate_distinguished_triangle' +HomotopyCategory.Pretriangulated.rotate_distinguished_triangle' +HurwitzZeta.jacobiTheta₂'_functional_equation' +HurwitzZeta.oddKernel_def' +Hyperreal.isSt_st' +Icc_mem_nhdsWithin_Ici' +Icc_mem_nhdsWithin_Iic' +Icc_mem_nhdsWithin_Iio' +Icc_mem_nhdsWithin_Ioi' +Ico_mem_nhdsWithin_Ici' +Ico_mem_nhdsWithin_Iio' +Ico_mem_nhdsWithin_Ioi' +Ideal.comap_map_of_surjective' +Ideal.comap_sInf' +Ideal.eq_jacobson_iff_sInf_maximal' +Ideal.isJacobson_iff_sInf_maximal' +Ideal.isJacobson_of_isIntegral' +Ideal.isMaximal_comap_of_isIntegral_of_isMaximal' +Ideal.IsMaximal.isPrime' +Ideal.isMaximal_of_isIntegral_of_isMaximal_comap' +Ideal.isPrime_ideal_prod_top' +Ideal.IsPrime.inf_le' +Ideal.isPrime_of_isPrime_prod_top' +Ideal.mem_span_insert' +Ideal.mem_span_singleton' +Ideal.MvPolynomial.quotient_mk_comp_C_isIntegral_of_jacobson' +Ideal.Polynomial.isMaximal_comap_C_of_isJacobson' +Ideal.quotientInfToPiQuotient_mk' +Ideal.Quotient.smulCommClass' +Ideal.span_mul_span' +Ideal.subset_union_prime' +IfExpr.eval_ite_ite' +iInf₂_mono' +iInf_le' +iInf_mono' +iInf_prod' +iInf_psigma' +iInf_range' +iInf_sigma' +iInf_subtype' +iInf_subtype'' +imageSubobjectIso_imageToKernel' +Imo1962Q1.ProblemPredicate' +imo1962_q4' +Imo1969Q1.not_prime_of_int_mul' +Imo2001Q2.imo2001_q2' +imp_or' +induced_orderTopology' +Inducing.continuousAt_iff' +Inducing.isClosed_iff' +inf_compl_eq_bot' +inf_eq_half_smul_add_sub_abs_sub' +inner_map_polarization' +InnerProductSpaceable.add_left_aux2' +InnerProductSpaceable.add_left_aux4' +Inseparable.specializes' +Int.add_le_zero_iff_le_neg' +Int.add_nonnneg_iff_neg_le' +Int.ceil_eq_on_Ioc' +Int.coprime_of_sq_sum' +Int.dist_eq' +integrable_cexp_quadratic' +integrableOn_Icc_iff_integrableOn_Ico' +integrableOn_Icc_iff_integrableOn_Ioc' +integrableOn_Icc_iff_integrableOn_Ioo' +integrableOn_Ici_iff_integrableOn_Ioi' +integrableOn_Ico_iff_integrableOn_Ioo' +integrableOn_Iic_iff_integrableOn_Iio' +integrableOn_Ioc_iff_integrableOn_Ioo' +Int.eq_one_or_neg_one_of_mul_eq_neg_one' +Int.eq_one_or_neg_one_of_mul_eq_one' +interior_closedBall' +interior_eq_nhds' +interior_Ici' +interior_Iic' +interior_sphere' +IntermediateField.algebra' +IntermediateField.charP' +IntermediateField.eq_of_le_of_finrank_le'' +IntermediateField.exists_algHom_adjoin_of_splits'' +IntermediateField.exists_algHom_of_splits' +IntermediateField.exists_finset_of_mem_supr' +IntermediateField.exists_finset_of_mem_supr'' +IntermediateField.expChar' +IntermediateField.finInsepDegree_bot' +IntermediateField.finiteDimensional_iSup_of_finset' +IntermediateField.finrank_bot' +IntermediateField.finrank_top' +IntermediateField.finSepDegree_bot' +IntermediateField.insepDegree_bot' +IntermediateField.lift_insepDegree_bot' +IntermediateField.lift_sepDegree_bot' +IntermediateField.module' +IntermediateField.normalClosure_def' +IntermediateField.normalClosure_def'' +IntermediateField.normal_iff_forall_map_eq' +IntermediateField.normal_iff_forall_map_le' +IntermediateField.rank_bot' +IntermediateField.rank_top' +IntermediateField.sepDegree_bot' +intermediate_value_Ico' +intermediate_value_Ioc' +intermediate_value_Ioo' +IntervalIntegrable.aestronglyMeasurable' +intervalIntegrable_iff' +IntervalIntegrable.mono_fun' +IntervalIntegrable.mono_set' +intervalIntegral.continuous_parametric_intervalIntegral_of_continuous' +intervalIntegral.integral_congr_ae' +intervalIntegral.integral_const' +intervalIntegral.integral_deriv_comp_mul_deriv' +intervalIntegral.integral_deriv_comp_smul_deriv' +intervalIntegral.integral_deriv_eq_sub' +intervalIntegral.integral_interval_sub_interval_comm' +Int.even_add' +Int.even_or_odd' +Int.even_pow' +Int.even_sub' +Int.even_xor'_odd' +Int.exists_gcd_one' +Int.floor_eq_on_Ico' +Int.Matrix.exists_ne_zero_int_vec_norm_le' +Int.ModEq.add_left_cancel' +Int.ModEq.add_right_cancel' +Int.ModEq.mul_left' +Int.ModEq.mul_right' +Int.natAbs_ofNat' +Int.odd_add' +Int.odd_pow' +Int.odd_sub' +Int.Prime.dvd_mul' +Int.Prime.dvd_pow' +Int.toNat_lt' +Int.two_pow_sub_pow' +inv_div' +inv_le' +inv_le_div_iff_le_mul' +inv_le_iff_one_le_mul' +inv_le_inv' +inv_lt' +inv_lt_div_iff_lt_mul' +inv_lt_iff_one_lt_mul' +inv_lt_inv' +inv_mul' +inv_mul_le_iff' +inv_mul_le_iff_le_mul' +inv_mul_lt_iff' +inv_mul_lt_iff_lt_mul' +inv_neg' +inv_neg'' +invOf_mul_cancel_left' +invOf_mul_cancel_right' +invOf_mul_self' +invOf_one' +inv_pos_le_iff_one_le_mul' +inv_pos_lt_iff_one_lt_mul' +inv_zpow' +Ioc_mem_nhdsWithin_Iic' +Ioc_mem_nhdsWithin_Iio' +Ioc_mem_nhdsWithin_Ioi' +Ioo_mem_nhdsWithin_Iio' +Ioo_mem_nhdsWithin_Ioi' +IsAbsoluteValue.abv_one' +isAddFundamentalDomain_Ioc' +isAdjointPair_toBilin' +isAdjointPair_toLinearMap₂' +IsAlgClosed.algebraMap_surjective_of_isIntegral' +IsAntichain.eq' +IsAntichain.interior_eq_empty' +isArtinian_of_fg_of_artinian' +isArtinian_submodule' +IsBaseChange.algHom_ext' +IsBoundedBilinearMap.isBigO' +isBounded_iff_forall_norm_le' +isBoundedUnder_ge_finset_inf' +isBoundedUnder_le_finset_sup' +IsCauSeq.bounded' +isClosed_induced_iff' +isCoboundedUnder_ge_finset_inf' +isCoboundedUnder_le_finset_sup' +IsCompact.elim_nhds_subcover' +IsCompact.elim_nhds_subcover_nhdsSet' +IsCompact.exists_bound_of_continuousOn' +isCompact_iff_ultrafilter_le_nhds' +IsCompact.tendsto_subseq' +isComplete_iff_ultrafilter' +IsCoprime.isUnit_of_dvd' +IsCyclotomicExtension.neZero' +IsCyclotomicExtension.Rat.discr_odd_prime' +IsDedekindDomain.HeightOneSpectrum.adicCompletion.algebra' +IsDedekindDomain.HeightOneSpectrum.adicCompletion.instIsScalarTower' +IsDedekindDomain.HeightOneSpectrum.adicValued.has_uniform_continuous_const_smul' +IsDedekindDomain.HeightOneSpectrum.algebraMap_adicCompletion' +isField_of_isIntegral_of_isField' +IsFractionRing.mk'_num_den' +IsFractionRing.num_mul_den_eq_num_iff_eq' +IsGLB.exists_between' +IsGLB.exists_between_self_add' +isGLB_inv' +IsGroupHom.inv_iff_ker' +IsGroupHom.inv_ker_one' +IsGroupHom.map_mul' +IsGroupHom.one_iff_ker_inv' +IsGroupHom.one_ker_inv' +IsIntegralClosure.algebraMap_mk' +isIntegral_localization' +IsIntegral.minpoly_splits_tower_top' +IsIntegral.of_mem_closure'' +IsInvariantSubring.coe_subtypeHom' +IsKleinFour.card_four' +IsLindelof.elim_nhds_subcover' +IsLinearMap.isLinearMap_smul' +IsLocalization.algebraMap_mk' +IsLocalization.algEquiv_mk' +IsLocalization.algEquiv_symm_mk' +IsLocalization.map_id_mk' +IsLocalization.map_mk' +IsLocalization.mem_invSubmonoid_iff_exists_mk' +IsLocalization.mk'_eq_iff_eq' +IsLocalization.mk'_eq_of_eq' +IsLocalization.mk'_mul_mk'_eq_one' +IsLocalization.mk'_self' +IsLocalization.mk'_self'' +IsLocalization.mk'_spec' +IsLocalization.ringEquivOfRingEquiv_mk' +IsLocalization.smul_mk' +IsLocalization.surj'' +IsLocalization.toInvSubmonoid_eq_mk' +isLocalizedModule_iff_isLocalization' +IsLocalizedModule.iso_symm_apply' +IsLocalizedModule.map_mk' +IsLocalizedModule.mk'_add_mk' +IsLocalizedModule.mk'_cancel' +IsLocalizedModule.mk_eq_mk' +IsLocalizedModule.mk'_eq_zero' +IsLocalizedModule.mk'_mul_mk' +IsLocalizedModule.mk'_sub_mk' +IsLowerSet.cthickening' +IsLowerSet.thickening' +isLUB_csSup' +IsLUB.exists_between' +IsLUB.exists_between_sub_self' +isLUB_hasProd' +isLUB_inv' +IsMax.not_isMin' +IsMin.not_isMax' +isNoetherian_iff' +isNoetherian_submodule' +IsometryEquiv.comp_continuous_iff' +isOpen_extChartAt_preimage' +isOpen_gt' +isOpen_iff_ultrafilter' +IsOpen.ite' +isOpen_lt' +isOpen_pi_iff' +IsPathConnected.exists_path_through_family' +IsPGroup.to_sup_of_normal_left' +IsPGroup.to_sup_of_normal_right' +IsPreconnected.union' +IsPrimitiveRoot.card_rootsOfUnity' +IsPrimitiveRoot.finite_quotient_span_sub_one' +IsPrimitiveRoot.isPrimitiveRoot_iff' +IsPrimitiveRoot.isUnit_unit' +IsPrimitiveRoot.neZero' +IsPrimitiveRoot.zmodEquivZPowers_symm_apply_pow' +IsPrimitiveRoot.zmodEquivZPowers_symm_apply_zpow' +isQuasiregular_iff_isUnit' +isRegular_iff_ne_zero' +isRegular_of_ne_zero' +IsScalarTower.coe_toAlgHom' +IsScalarTower.subalgebra' +IsScalarTower.to_smulCommClass' +IsSelfAdjoint.conjugate' +isSemisimpleModule_of_isSemisimpleModule_submodule' +IsUnifLocDoublingMeasure.eventually_measure_le_scaling_constant_mul' +IsUnifLocDoublingMeasure.exists_measure_closedBall_le_mul' +isUnit_iff_exists_inv' +IsUnit.map' +IsUnit.val_inv_unit' +iSup₂_mono' +iSup_mono' +iSup_of_empty' +IsUpperSet.cthickening' +IsUpperSet.thickening' +iSup_prod' +iSup_psigma' +iSup_range' +iSup_sigma' +iSup_subtype' +iSup_subtype'' +ite_eq_iff' +iteratedFDeriv_add_apply' +iteratedFDeriv_const_smul_apply' +iteratedFDerivWithin_eventually_congr_set' +iter_deriv_inv' +iter_deriv_pow' +iter_deriv_zpow' +jacobiTheta₂'_add_left' +KaehlerDifferential.isScalarTower' +KaehlerDifferential.module' +LatticeHom.coe_comp_inf_hom' +LatticeHom.coe_comp_sup_hom' +LawfulFix.fix_eq' +lcm_assoc' +lcm_comm' +le_abs' +le_add_tsub' +Lean.Elab.Tactic.TacticM.runCore' +le_ciInf_iff' +le_ciSup_iff' +le_csInf_iff' +le_csInf_iff'' +le_csSup_iff' +le_div_iff₀' +le_div_iff_mul_le' +le_div_iff_of_neg' +LeftOrdContinuous.map_sSup' +Left.pow_lt_one_iff' +legendreSym.eq_neg_one_iff' +legendreSym.eq_one_iff' +le_hasProd' +le_iff_exists_mul' +le_iff_forall_one_lt_lt_mul' +le_inv' +le_iSup' +le_map_add_map_div' +le_mul_iff_one_le_left' +le_mul_iff_one_le_right' +le_mul_of_le_of_one_le' +le_mul_of_one_le_left' +le_mul_of_one_le_right' +le_nhdsAdjoint_iff' +le_of_eq_of_le' +le_of_forall_le' +le_of_forall_lt' +le_of_forall_one_lt_lt_mul' +le_of_le_of_eq' +le_of_mul_le_mul_left' +le_of_mul_le_mul_right' +le_of_pow_le_pow_left' +le_of_tendsto' +le_of_tendsto_of_tendsto' +le_tprod' +le_trans' +Lex.instDistribMulAction' +Lex.instDistribSMul' +Lex.instIsScalarTower' +Lex.instIsScalarTower'' +Lex.instModule' +Lex.instMulAction' +Lex.instMulActionWithZero' +Lex.instPow' +Lex.instSMulCommClass' +Lex.instSMulCommClass'' +Lex.instSMulWithZero' +LieAlgebra.IsKilling.apply_coroot_eq_cast' +LieAlgebra.IsKilling.coe_corootSpace_eq_span_singleton' +LieAlgebra.lieCharacter_apply_lie' +LieAlgebra.mem_corootSpace' +LieIdeal.map_sup_ker_eq_map' +LieModule.chainTop_isNonZero' +LieModule.coe_chainTop' +LieModule.genWeightSpaceChain_def' +LieModule.independent_genWeightSpace' +LieModule.instIsTrivialOfSubsingleton' +LieModule.isNilpotent_of_top_iff' +LieModule.iSup_genWeightSpace_eq_top' +LieModule.Weight.ext_iff' +LieSubalgebra.coe_incl' +LieSubalgebra.ext_iff' +LieSubalgebra.mem_normalizer_iff' +LieSubmodule.iSup_induction' +LieSubmodule.lieIdeal_oper_eq_linear_span' +LieSubmodule.mem_mk_iff' +LieSubmodule.module' +LieSubmodule.Quotient.mk_eq_zero' +LieSubmodule.Quotient.module' +LieSubmodule.Quotient.range_mk' +LieSubmodule.Quotient.surjective_mk' +LieSubmodule.Quotient.toEnd_comp_mk' +LieSubmodule.sInf_coe_toSubmodule' +LieSubmodule.sSup_coe_toSubmodule' +liftOfDerivationToSquareZero_mk_apply' +lift_rank_lt_rank_dual' +LightProfinite.proj_comp_transitionMap' +LightProfinite.proj_comp_transitionMapLE' +liminf_finset_inf' +limsup_finset_sup' +linearDependent_comp_subtype' +LinearEquiv.apply_smulCommClass' +LinearEquiv.coe_toContinuousLinearEquiv' +LinearEquiv.coe_toContinuousLinearEquiv_symm' +LinearEquiv.isRegular_congr' +LinearEquiv.isSMulRegular_congr' +LinearEquiv.isWeaklyRegular_congr' +LinearEquiv.mk_coe' +linearIndependent_algHom_toLinearMap' +LinearIndependent.cardinal_le_rank' +linearIndependent_equiv' +LinearIndependent.eq_zero_of_pair' +linearIndependent_fin_succ' +linearIndependent_iff' +linearIndependent_iff'' +linearIndependent_inl_union_inr' +linearIndependent_insert' +linearIndependent_le_span_aux' +linearIndependent_option' +LinearIndependent.span_eq_top_of_card_eq_finrank' +LinearIndependent.to_subtype_range' +LinearIsometry.completeSpace_map' +LinearIsometryEquiv.coe_coe'' +LinearIsometryEquiv.comp_fderiv' +LinearIsometryEquiv.comp_hasFDerivAt_iff' +LinearIsometryEquiv.comp_hasFDerivWithinAt_iff' +LinearIsometry.isComplete_image_iff' +LinearIsometry.isComplete_map_iff' +LinearIsometry.map_orthogonalProjection' +LinearMap.apply_smulCommClass' +LinearMap.BilinForm.mul_toMatrix' +LinearMap.BilinForm.nondegenerate_toBilin'_of_det_ne_zero' +LinearMap.BilinForm.Nondegenerate.toMatrix' +LinearMap.BilinForm.toMatrix'_toBilin' +LinearMap.coe_toContinuousLinearMap' +LinearMap.detAux_def'' +LinearMap.det_toLin' +LinearMap.det_toMatrix' +LinearMap.det_zero' +LinearMap.det_zero'' +LinearMap.disjoint_ker' +LinearMap.dualMap_apply' +LinearMap.extendScalarsOfIsLocalization_apply' +LinearMap.IsProj.eq_conj_prod_map' +LinearMap.IsScalarTower.compatibleSMul' +LinearMap.IsSymmetric.orthogonalComplement_iSup_eigenspaces_eq_bot' +LinearMap.IsSymmetric.orthogonalFamily_eigenspaces' +LinearMap.ker_eq_bot' +LinearMap.ker_smul' +LinearMap.lcomp_apply' +LinearMap.llcomp_apply' +LinearMap.map_le_map_iff' +LinearMap.minpoly_toMatrix' +LinearMap.mkContinuous₂_norm_le' +LinearMap.mul_apply' +LinearMap.mul_toMatrix' +LinearMap.ofIsCompl_eq' +LinearMap.range_smul' +LinearMap.separatingLeft_toLinearMap₂'_of_det_ne_zero' +LinearMap.SeparatingLeft.toMatrix₂' +LinearMap.stdBasis_apply' +LinearMap.toMatrixAlgEquiv_apply' +LinearMap.toMatrixAlgEquiv'_toLinAlgEquiv' +LinearMap.toMatrixAlgEquiv_transpose_apply' +LinearMap.toMatrix_apply' +LinearMap.toMatrix'_toLin' +LinearMap.toMatrix'_toLinearMap₂' +LinearMap.toMatrix'_toLinearMapₛₗ₂' +LinearMap.toMatrix_transpose_apply' +LinearMap.trace_comp_comm' +LinearMap.trace_conj' +LinearMap.trace_eq_sum_trace_restrict' +LinearMap.trace_mul_cycle' +LinearMap.trace_prodMap' +LinearMap.trace_tensorProduct' +LinearMap.trace_transpose' +LinearOrderedCommGroup.mul_lt_mul_left' +LinearPMap.closure_def' +LinearPMap.ext' +LinearPMap.mem_graph_iff' +LinearPMap.mem_graph_snd_inj' +LinearPMap.toFun' +lineDerivWithin_congr' +LipschitzOnWith.of_dist_le' +LipschitzWith.const' +LipschitzWith.integral_inv_smul_sub_mul_tendsto_integral_lineDeriv_mul' +LipschitzWith.nnorm_le_mul' +LipschitzWith.norm_le_mul' +LipschitzWith.of_dist_le' +lipschitzWith_one_nnnorm' +lipschitzWith_one_norm' +List.aemeasurable_prod' +List.aestronglyMeasurable_prod' +List.alternatingProd_cons' +List.alternatingProd_cons_cons' +list_casesOn' +List.chain'_cons' +List.Chain'.cons' +List.chain'_map_of_chain' +list_cons' +List.cons_sublist_cons' +List.count_cons' +List.decidableChain' +List.dedup_cons_of_mem' +List.dedup_cons_of_not_mem' +List.destutter_cons' +List.destutter'_is_chain' +List.destutter_is_chain' +List.destutter_of_chain' +List.drop_take_succ_join_eq_get' +List.exists_le_of_prod_le' +List.exists_lt_of_prod_lt' +List.ext_get?' +List.ext_get?_iff' +List.filter_attach' +List.filter_subset' +list_foldl' +List.foldl_eq_foldr' +List.foldl_eq_of_comm' +List.foldl_fixed' +List.foldr_eq_of_comm' +List.foldr_fixed' +List.Forall₂.prod_le_prod' +List.getLast_append' +List.getLast_concat' +List.getLast_singleton' +List.get_reverse' +List.get?_zipWith' +List.inter_nil' +List.isRotated_nil_iff' +List.isRotated_singleton_iff' +List.LE' +List.left_unique_forall₂' +List.le_maximum_of_mem' +List.length_foldr_permutationsAux2' +List.length_mergeSort' +List.length_rotate' +List.length_sublists' +List.lookmap_id' +List.LT' +List.map₂Left_eq_map₂Left' +List.map₂Right_eq_map₂Right' +List.map_filter' +List.map_mergeSort' +List.map_permutations' +List.map_permutationsAux2' +List.measurable_prod' +List.mem_destutter' +List.mem_mergeSort' +List.mem_permutations' +List.mem_permutationsAux2' +List.mem_sublists' +List.minimum_le_of_mem' +List.Nat.antidiagonal_succ' +List.Nat.antidiagonal_succ_succ' +List.next_cons_cons_eq' +List.nnnorm_prod_le' +List.nodup_sublists' +List.norm_prod_le' +List.not_lt_maximum_of_mem' +List.not_lt_minimum_of_mem' +List.ofFn_succ' +List.Pairwise.chain' +List.pairwise_map' +List.Pairwise.sublists' +List.perm_mergeSort' +List.Perm.permutations' +List.permutations_perm_permutations' +List.prev_cons_cons_eq' +List.prev_cons_cons_of_ne' +List.prev_getLast_cons' +List.prod_le_prod' +List.prod_lt_prod' +List.replicate_right_inj' +List.replicate_succ' +list_reverse' +List.reverse_concat' +List.reverse_cons' +List.revzip_sublists' +List.right_unique_forall₂' +List.rotate_eq_rotate' +List.rotate'_rotate' +Lists' +Lists.lt_sizeof_cons' +Lists'.mem_of_subset' +List.smul_prod' +List.sorted_mergeSort' +List.stronglyMeasurable_prod' +List.SublistForall₂.prod_le_prod' +List.sublists_eq_sublists' +List.sublistsLen_sublist_sublists' +List.sublists_perm_sublists' +List.support_formPerm_le' +List.support_formPerm_of_nodup' +List.takeD_left' +List.takeI_left' +List.tendsto_insertNth' +List.zipLeft_eq_zipLeft' +List.zipRight_eq_zipRight' +List.zipWith_swap_prod_support' +localCohomology.moduleCat_enoughProjectives' +Localization.algEquiv_mk' +Localization.algEquiv_symm_mk' +Localization.Away.mk_eq_monoidOf_mk' +Localization.epi' +Localization.liftOn₂_mk' +Localization.liftOn_mk' +Localization.localRingHom_mk' +Localization.mk_eq_mk' +Localization.mk_eq_mk_iff' +Localization.mk_eq_monoidOf_mk' +Localization.mulEquivOfQuotient_mk' +Localization.mulEquivOfQuotient_symm_mk' +localization_unit_isIso' +LocalizedModule.add_assoc' +LocalizedModule.add_comm' +LocalizedModule.add_zero' +LocalizedModule.algebra' +LocalizedModule.algebraMap_mk' +LocalizedModule.isModule' +LocalizedModule.mul_smul' +LocalizedModule.nsmul_succ' +LocalizedModule.nsmul_zero' +LocalizedModule.zero_add' +LocallyFinite.continuous' +LocallyFinite.continuousOn_iUnion' +LocallyFinite.option_elim' +LocalRing.of_surjective' +logDeriv_id' +lowerClosure_interior_subset' +lp.eq_zero' +lp.norm_le_of_forall_le' +lp.norm_nonneg' +lp.tsum_mul_le_mul_norm' +LSeries.abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable' +lt_div_iff' +lt_div_iff_mul_lt' +lt_div_iff_of_neg' +lt_iff_lt_of_le_iff_le' +lt_inv' +lt_inv_iff_mul_lt_one' +LT.lt.ne' +lt_mul_iff_one_lt_left' +lt_mul_iff_one_lt_right' +lt_mul_of_le_of_one_lt' +lt_mul_of_lt_of_one_le' +lt_mul_of_lt_of_one_lt' +lt_mul_of_one_lt_left' +lt_mul_of_one_lt_of_lt' +lt_mul_of_one_lt_right' +lt_of_eq_of_lt' +lt_of_le_of_lt' +lt_of_le_of_ne' +lt_of_lt_of_eq' +lt_of_lt_of_le' +lt_of_mul_lt_mul_left' +lt_of_mul_lt_mul_right' +lt_of_pow_lt_pow_left' +lt_trans' +mabs_le' +Magma.AssocQuotient.lift_comp_of' +MapClusterPt.tendsto_comp' +map_comp_div' +map_comp_zpow' +map_div' +map_extChartAt_nhds' +map_extChartAt_nhdsWithin' +map_extChartAt_nhdsWithin_eq_image' +map_extChartAt_symm_nhdsWithin' +map_extChartAt_symm_nhdsWithin_range' +map_finset_inf' +map_finset_sup' +map_natCast' +map_ofNat' +map_preNormEDS' +mapsTo_omegaLimit' +map_zpow' +Mathlib.Meta.Finset.range_succ' +Mathlib.Meta.Finset.range_zero' +Mathlib.Meta.FunProp.StateList.toList' +Mathlib.Meta.List.range_succ_eq_map' +Mathlib.Meta.List.range_zero' +Mathlib.Meta.Multiset.range_succ' +Mathlib.Meta.Multiset.range_zero' +Mathlib.Meta.NormNum.jacobiSymNat.qr₁' +Mathlib.Meta.Positivity.lt_of_le_of_ne' +Mathlib.Tactic.ComputeDegree.coeff_pow_of_natDegree_le_of_eq_ite' +Mathlib.Tactic.ComputeDegree.degree_eq_of_le_of_coeff_ne_zero' +Mathlib.Tactic.Group.zpow_trick_one' +Mathlib.Tactic.Ring.atom_pf' +Mathlib.Util.addAndCompile' +Mathlib.Vector.eraseIdx_insertNth' +Mathlib.Vector.prod_set' +Mathlib.WhatsNew.mkHeader' +Matrix.blockDiag'_blockDiagonal' +Matrix.blockDiagonal'_apply' +Matrix.blockDiagonal_apply' +Matrix.blockTriangular_blockDiagonal' +Matrix.blockTriangular_stdBasisMatrix' +Matrix.blockTriangular_transvection' +Matrix.cons_val' +Matrix.cons_val_succ' +Matrix.cons_val_zero' +Matrix.det_apply' +Matrix.det_units_conj' +Matrix.det_updateColumn_smul' +Matrix.det_updateRow_smul' +Matrix.diagonal_apply_ne' +Matrix.diagonal_intCast' +Matrix.diagonal_mul_diagonal' +Matrix.diagonal_natCast' +Matrix.diagonal_ofNat' +Matrix.diagonal_toLin' +Matrix.dotProduct_diagonal' +Matrix.dotProduct_zero' +Matrix.empty_val' +Matrix.exists_mulVec_eq_zero_iff' +Matrix.exp_blockDiagonal' +Matrix.exp_conj' +Matrix.exp_units_conj' +Matrix.head_val' +Matrix.induction_on' +Matrix.inv_pow' +Matrix.inv_smul' +Matrix.inv_zpow' +Matrix.isAdjointPair_equiv' +Matrix.ker_diagonal_toLin' +Matrix.kronecker_assoc' +Matrix.kroneckerTMul_assoc' +Matrix.map_id' +Matrix.mem_orthogonalGroup_iff' +Matrix.mem_unitaryGroup_iff' +Matrix.minpoly_toLin' +Matrix.mul_apply' +Matrix.Nondegenerate.toBilin' +Matrix.Nondegenerate.toLinearMap₂' +Matrix.one_apply_ne' +Matrix.PosDef.of_toQuadraticForm' +Matrix.PosDef.toQuadraticForm' +Matrix.pow_inv_comm' +Matrix.pow_sub' +Matrix.range_toLin' +Matrix.represents_iff' +Matrix.tail_val' +Matrix.toBilin'_apply' +Matrix.toBilin'_toMatrix' +Matrix.toLinAlgEquiv'_toMatrixAlgEquiv' +Matrix.toLin'_apply' +Matrix.toLinearMap₂'_apply' +Matrix.toLinearMap₂'_toMatrix' +Matrix.toLinearMapₛₗ₂'_toMatrix' +Matrix.toLin'_toMatrix' +Matrix.trace_blockDiagonal' +Matrix.trace_mul_cycle' +Matrix.twoBlockTriangular_det' +Matrix.vec2_dotProduct' +Matrix.vec3_dotProduct' +Matrix.zero_dotProduct' +Matrix.zpow_mul' +Matroid.Base.exchange_base_of_indep' +Matroid.base_restrict_iff' +Matroid.Basis.basis' +Matroid.basis_iff' +Matroid.basis_iff_basis_closure_of_subset' +Matroid.basis_restrict_iff' +Matroid.closure_def' +Matroid.coindep_iff_exists' +Matroid.dual_base_iff' +Matroid.dual_indep_iff_exists' +Matroid.exists_basis' +Matroid.Finitary.sum' +Matroid.Indep.mem_closure_iff' +Matroid.map_basis_iff' +Matroid.mapSetEmbedding_indep_iff' +Matroid.mem_closure_of_mem' +Matroid.restrictSubtype_dual' +Matroid.subset_closure_of_subset' +Matroid.uniqueBaseOn_indep_iff' +Matroid.uniqueBaseOn_restrict' +max_def' +max_div_div_left' +max_div_div_right' +max_div_min_eq_mabs' +maximal_subset_iff' +max_inv_inv' +max_mul_mul_le_max_mul_max' +max_rec' +mdifferentiableWithinAt_iff' +mdifferentiableWithinAt_inter' +Measurable.comp' +Measurable.comp_aemeasurable' +Measurable.const_smul' +Measurable.div' +MeasurableEmbedding.withDensity_ofReal_comap_apply_eq_integral_abs_deriv_mul' +Measurable.ennreal_tsum' +MeasurableEquiv.withDensity_ofReal_map_symm_apply_eq_integral_abs_deriv_mul' +measurable_findGreatest' +measurable_from_prod_countable' +measurable_id' +measurable_id'' +Measurable.inf' +Measurable.iSup' +Measurable.lintegral_kernel_prod_left' +Measurable.lintegral_kernel_prod_right' +Measurable.lintegral_kernel_prod_right'' +Measurable.mul' +measurable_of_isClosed' +measurable_quotient_mk' +measurable_quotient_mk'' +measurableSet_eq_fun' +MeasurableSet.image_inclusion' +measurableSet_le' +measurableSet_lt' +Measurable.sup' +measurable_to_countable' +measurable_tProd_elim' +MeasureTheory.abs_toReal_measure_sub_le_measure_symmDiff' +MeasureTheory.adapted_predictablePart' +MeasureTheory.addContent_union' +MeasureTheory.AECover.integrable_of_lintegral_nnnorm_bounded' +MeasureTheory.AECover.integrable_of_lintegral_nnnorm_tendsto' +MeasureTheory.ae_eq_comp' +MeasureTheory.ae_eq_dirac' +MeasureTheory.ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' +MeasureTheory.ae_eq_trim_iff_of_aeStronglyMeasurable' +MeasureTheory.ae_lt_top' +MeasureTheory.aemeasurable_withDensity_ennreal_iff' +MeasureTheory.ae_restrict_iff' +MeasureTheory.AEStronglyMeasurable.comp_ae_measurable' +MeasureTheory.AEStronglyMeasurable.const_smul' +MeasureTheory.AEStronglyMeasurable.convolution_integrand' +MeasureTheory.AEStronglyMeasurable.convolution_integrand_snd' +MeasureTheory.AEStronglyMeasurable.convolution_integrand_swap_snd' +MeasureTheory.AEStronglyMeasurable'.of_subsingleton' +MeasureTheory.ae_withDensity_iff' +MeasureTheory.ae_withDensity_iff_ae_restrict' +MeasureTheory.average_eq' +MeasureTheory.condexp_bot' +MeasureTheory.condexpIndL1Fin_smul' +MeasureTheory.condexpIndL1_smul' +MeasureTheory.condexpInd_smul' +MeasureTheory.condexpIndSMul_smul' +MeasureTheory.condexpL1CLM_of_aestronglyMeasurable' +MeasureTheory.condexpL1_of_aestronglyMeasurable' +MeasureTheory.condexp_of_aestronglyMeasurable' +MeasureTheory.Content.innerContent_mono' +MeasureTheory.diracProba_toMeasure_apply' +MeasureTheory.eLpNorm_add_le' +MeasureTheory.eLpNorm'_const' +MeasureTheory.eLpNorm_const' +MeasureTheory.eLpNorm_eq_eLpNorm' +MeasureTheory.eLpNorm'_eq_zero_of_ae_zero' +MeasureTheory.eLpNorm_indicator_const' +MeasureTheory.eLpNorm'_le_eLpNorm'_mul_eLpNorm' +MeasureTheory.eLpNorm_nnreal_eq_eLpNorm' +MeasureTheory.eLpNorm_one_le_of_le' +MeasureTheory.eLpNorm'_smul_le_mul_eLpNorm' +MeasureTheory.eLpNorm_sub_le' +MeasureTheory.eLpNorm'_zero' +MeasureTheory.eLpNorm_zero' +MeasureTheory.exp_llr_of_ac' +MeasureTheory.exp_neg_llr' +MeasureTheory.Filtration.stronglyMeasurable_limit_process' +MeasureTheory.hasFiniteIntegral_congr' +MeasureTheory.HasFiniteIntegral.congr' +MeasureTheory.HasFiniteIntegral.mono' +MeasureTheory.hasFiniteIntegral_prod_iff' +MeasureTheory.HasPDF.congr' +MeasureTheory.Ico_ae_eq_Icc' +MeasureTheory.Ico_ae_eq_Ioc' +MeasureTheory.Iio_ae_eq_Iic' +MeasureTheory.inducedOuterMeasure_eq' +MeasureTheory.inducedOuterMeasure_eq_extend' +MeasureTheory.Integrable.add' +MeasureTheory.Integrable.bdd_mul' +MeasureTheory.Integrable.comp_mul_left' +MeasureTheory.Integrable.comp_mul_right' +MeasureTheory.integrable_congr' +MeasureTheory.Integrable.congr' +MeasureTheory.Integrable.const_mul' +MeasureTheory.integrable_finset_sum' +MeasureTheory.Integrable.mono' +MeasureTheory.Integrable.mul_const' +MeasureTheory.integrable_of_forall_fin_meas_le' +MeasureTheory.Integrable.simpleFunc_mul' +MeasureTheory.Integrable.toL1_smul' +MeasureTheory.integrable_withDensity_iff_integrable_smul' +MeasureTheory.integral_add' +MeasureTheory.integral_countable' +MeasureTheory.integral_dirac' +MeasureTheory.integral_Icc_eq_integral_Ico' +MeasureTheory.integral_Icc_eq_integral_Ioc' +MeasureTheory.integral_Icc_eq_integral_Ioo' +MeasureTheory.integral_Ici_eq_integral_Ioi' +MeasureTheory.integral_Ico_eq_integral_Ioo' +MeasureTheory.integral_Iic_eq_integral_Iio' +MeasureTheory.integral_Ioc_eq_integral_Ioo' +MeasureTheory.integral_neg' +MeasureTheory.integral_singleton' +MeasureTheory.integral_sub' +MeasureTheory.integral_zero' +MeasureTheory.Ioc_ae_eq_Icc' +MeasureTheory.Ioi_ae_eq_Ici' +MeasureTheory.Ioo_ae_eq_Icc' +MeasureTheory.Ioo_ae_eq_Ico' +MeasureTheory.Ioo_ae_eq_Ioc' +MeasureTheory.isClosed_aeStronglyMeasurable' +MeasureTheory.isComplete_aeStronglyMeasurable' +MeasureTheory.IsFundamentalDomain.integral_eq_tsum' +MeasureTheory.IsFundamentalDomain.integral_eq_tsum'' +MeasureTheory.IsFundamentalDomain.lintegral_eq_tsum' +MeasureTheory.IsFundamentalDomain.lintegral_eq_tsum'' +MeasureTheory.IsFundamentalDomain.measure_eq_tsum' +MeasureTheory.IsFundamentalDomain.setIntegral_eq_tsum' +MeasureTheory.IsFundamentalDomain.setLIntegral_eq_tsum' +MeasureTheory.IsStoppingTime.measurableSet_eq' +MeasureTheory.IsStoppingTime.measurableSet_eq_of_countable' +MeasureTheory.IsStoppingTime.measurableSet_eq_of_countable_range' +MeasureTheory.IsStoppingTime.measurableSet_ge' +MeasureTheory.IsStoppingTime.measurableSet_ge_of_countable' +MeasureTheory.IsStoppingTime.measurableSet_ge_of_countable_range' +MeasureTheory.IsStoppingTime.measurableSet_gt' +MeasureTheory.IsStoppingTime.measurableSet_le' +MeasureTheory.IsStoppingTime.measurableSet_lt' +MeasureTheory.IsStoppingTime.measurableSet_lt_of_countable' +MeasureTheory.IsStoppingTime.measurableSet_lt_of_countable_range' +MeasureTheory.IsStoppingTime.measurableSpace_le' +MeasureTheory.L1.norm_setToL1_le' +MeasureTheory.L1.norm_setToL1_le_mul_norm' +MeasureTheory.L1.setToL1_add_left' +MeasureTheory.L1.setToL1_congr_left' +MeasureTheory.L1.setToL1_eq_setToL1' +MeasureTheory.L1.setToL1_mono_left' +MeasureTheory.L1.setToL1_smul_left' +MeasureTheory.L1.setToL1_zero_left' +MeasureTheory.L1.SimpleFunc.norm_setToL1SCLM_le' +MeasureTheory.L1.SimpleFunc.setToL1S_add_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_add_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_congr_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_mono_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_smul_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_zero_left' +MeasureTheory.L1.SimpleFunc.setToL1S_mono_left' +MeasureTheory.L1.SimpleFunc.setToL1S_smul_left' +MeasureTheory.L1.SimpleFunc.setToL1S_zero_left' +MeasureTheory.L2.add_left' +MeasureTheory.L2.norm_sq_eq_inner' +MeasureTheory.L2.smul_left' +MeasureTheory.laverage_eq' +MeasureTheory.lintegral_add_left' +MeasureTheory.lintegral_add_right' +MeasureTheory.lintegral_const_mul' +MeasureTheory.lintegral_const_mul'' +MeasureTheory.lintegral_count' +MeasureTheory.lintegral_countable' +MeasureTheory.lintegral_dirac' +MeasureTheory.lintegral_eq_zero_iff' +MeasureTheory.lintegral_finset_sum' +MeasureTheory.lintegral_iInf' +MeasureTheory.lintegral_map' +MeasureTheory.lintegral_mono' +MeasureTheory.lintegral_mono_fn' +MeasureTheory.lintegral_mono_set' +MeasureTheory.lintegral_mul_const' +MeasureTheory.lintegral_mul_const'' +MeasureTheory.lintegral_rpow_nnnorm_eq_rpow_eLpNorm' +MeasureTheory.lintegral_singleton' +MeasureTheory.lintegral_sub' +MeasureTheory.lintegral_sub_le' +MeasureTheory.lmarginal_union' +MeasureTheory.locallyIntegrable_finset_sum' +MeasureTheory.lowerCrossingTime_stabilize' +MeasureTheory.Lp.ae_tendsto_of_cauchy_eLpNorm' +MeasureTheory.Lp.eLpNorm'_lim_le_liminf_eLpNorm' +MeasureTheory.Lp.eLpNorm'_sum_norm_sub_le_tsum_of_cauchy_eLpNorm' +MeasureTheory.lpMeas.aeStronglyMeasurable' +MeasureTheory.Lp.norm_const' +MeasureTheory.Lp.simpleFunc.eq' +MeasureTheory.Lp.tendsto_Lp_iff_tendsto_ℒp' +MeasureTheory.Lp.tendsto_Lp_iff_tendsto_ℒp'' +MeasureTheory.measurableSet_filtrationOfSet' +MeasureTheory.measurableSet_sigmaFiniteSetWRT' +MeasureTheory.Measure.ae_sum_iff' +MeasureTheory.Measure.bind_zero_right' +MeasureTheory.Measure.count_apply_eq_top' +MeasureTheory.Measure.count_apply_finite' +MeasureTheory.Measure.count_apply_finset' +MeasureTheory.Measure.count_apply_lt_top' +MeasureTheory.Measure.count_eq_zero_iff' +MeasureTheory.Measure.count_injective_image' +MeasureTheory.Measure.count_ne_zero' +MeasureTheory.Measure.count_ne_zero'' +MeasureTheory.Measure.count_singleton' +MeasureTheory.measure_diff' +MeasureTheory.measure_diff_null' +MeasureTheory.Measure.dirac_apply' +MeasureTheory.Measure.empty_of_count_eq_zero' +MeasureTheory.Measure.ext_iff' +MeasureTheory.Measure.haveLebesgueDecompositionSMul' +MeasureTheory.Measure.InnerRegularWRT.map' +MeasureTheory.Measure.integral_toReal_rnDeriv' +MeasureTheory.measure_inter_conull' +MeasureTheory.Measure.inv_rnDeriv' +MeasureTheory.measure_iUnion_null_iff' +MeasureTheory.Measure.LebesgueDecomposition.iSup_mem_measurableLE' +MeasureTheory.Measure.LebesgueDecomposition.iSup_monotone' +MeasureTheory.Measure.le_iff' +MeasureTheory.Measure.lt_iff' +MeasureTheory.Measure.map_id' +MeasureTheory.Measure.measurable_bind' +MeasureTheory.Measure.MeasureDense.nonempty' +MeasureTheory.Measure.nonpos_iff_eq_zero' +MeasureTheory.Measure.pi_noAtoms' +MeasureTheory.MeasurePreserving.integral_comp' +MeasureTheory.Measure.restrict_apply₀' +MeasureTheory.Measure.restrict_apply_eq_zero' +MeasureTheory.Measure.restrict_restrict' +MeasureTheory.Measure.restrict_restrict₀' +MeasureTheory.Measure.restrict_singleton' +MeasureTheory.Measure.restrict_union' +MeasureTheory.Measure.restrict_union_add_inter' +MeasureTheory.Measure.rnDeriv_mul_rnDeriv' +MeasureTheory.Measure.rnDeriv_pos' +MeasureTheory.Measure.setIntegral_toReal_rnDeriv' +MeasureTheory.Measure.setIntegral_toReal_rnDeriv_eq_withDensity' +MeasureTheory.Measure.setLIntegral_rnDeriv' +MeasureTheory.Measure.sum_apply_eq_zero' +MeasureTheory.Measure.toSphere_apply' +MeasureTheory.Measure.toSphere_apply_univ' +MeasureTheory.measure_union' +MeasureTheory.measure_union₀' +MeasureTheory.measure_union_add_inter' +MeasureTheory.measure_union_add_inter₀' +MeasureTheory.memℒp_finset_sum' +MeasureTheory.Memℒp.integrable_norm_rpow' +MeasureTheory.Memℒp.meas_ge_lt_top' +MeasureTheory.mem_lpMeas_iff_aeStronglyMeasurable' +MeasureTheory.mem_lpMeasSubgroup_iff_aeStronglyMeasurable' +MeasureTheory.Memℒp.mono' +MeasureTheory.norm_indicatorConstLp' +MeasureTheory.norm_setIntegral_le_of_norm_le_const' +MeasureTheory.norm_setIntegral_le_of_norm_le_const_ae' +MeasureTheory.norm_setIntegral_le_of_norm_le_const_ae'' +MeasureTheory.norm_setToFun_le' +MeasureTheory.norm_setToFun_le_mul_norm' +MeasureTheory.NullMeasurable.measurable' +MeasureTheory.OuterMeasure.empty' +MeasureTheory.OuterMeasure.isCaratheodory_iff_le' +MeasureTheory.OuterMeasure.iUnion_null_iff' +MeasureTheory.OuterMeasure.le_boundedBy' +MeasureTheory.OuterMeasure.mono' +MeasureTheory.OuterMeasure.mono'' +MeasureTheory.OuterMeasure.top_apply' +MeasureTheory.OuterMeasure.trim_eq_iInf' +MeasureTheory.pdf.eq_of_map_eq_withDensity' +MeasureTheory.pdf.quasiMeasurePreserving_hasPDF' +MeasureTheory.piPremeasure_pi' +MeasureTheory.ProbabilityMeasure.tendsto_measure_of_null_frontier_of_tendsto' +MeasureTheory.ProgMeasurable.finset_prod' +MeasureTheory.progMeasurable_of_tendsto' +MeasureTheory.restrict_dirac' +MeasureTheory.restrict_withDensity' +MeasureTheory.setAverage_eq' +MeasureTheory.setIntegral_dirac' +MeasureTheory.setIntegral_tilted' +MeasureTheory.setLaverage_eq' +MeasureTheory.setLIntegral_dirac' +MeasureTheory.setLIntegral_eq_zero_iff' +MeasureTheory.setLIntegral_mono' +MeasureTheory.setLIntegral_mono_ae' +MeasureTheory.setLIntegral_tilted' +MeasureTheory.setLIntegral_withDensity_eq_lintegral_mul₀' +MeasureTheory.setLIntegral_withDensity_eq_setLIntegral_mul_non_measurable₀' +MeasureTheory.setToFun_add_left' +MeasureTheory.setToFun_congr_left' +MeasureTheory.setToFun_finset_sum' +MeasureTheory.setToFun_measure_zero' +MeasureTheory.setToFun_mono_left' +MeasureTheory.setToFun_smul_left' +MeasureTheory.setToFun_zero_left' +MeasureTheory.sigmaFinite_restrict_sigmaFiniteSetWRT' +MeasureTheory.SigmaFinite.withDensity_of_ne_top' +MeasureTheory.SignedMeasure.eq_singularPart' +MeasureTheory.SignedMeasure.exists_subset_restrict_nonpos' +MeasureTheory.SignedMeasure.haveLebesgueDecomposition_mk' +MeasureTheory.SignedMeasure.restrictNonposSeq_disjoint' +MeasureTheory.SignedMeasure.someExistsOneDivLT_subset' +MeasureTheory.SimpleFunc.extend_apply' +MeasureTheory.SimpleFunc.extend_comp_eq' +MeasureTheory.SimpleFunc.lintegral_eq_of_subset' +MeasureTheory.SimpleFunc.lintegral_map' +MeasureTheory.SimpleFunc.setToSimpleFunc_add_left' +MeasureTheory.SimpleFunc.setToSimpleFunc_congr' +MeasureTheory.SimpleFunc.setToSimpleFunc_const' +MeasureTheory.SimpleFunc.setToSimpleFunc_mono_left' +MeasureTheory.SimpleFunc.setToSimpleFunc_nonneg' +MeasureTheory.SimpleFunc.setToSimpleFunc_smul_left' +MeasureTheory.SimpleFunc.setToSimpleFunc_zero' +MeasureTheory.SimpleFunc.simpleFunc_bot' +MeasureTheory.stoppedProcess_eq' +MeasureTheory.stoppedProcess_eq'' +MeasureTheory.stoppedValue_eq' +MeasureTheory.stoppedValue_piecewise_const' +MeasureTheory.stoppedValue_sub_eq_sum' +MeasureTheory.StronglyMeasurable.aeStronglyMeasurable' +MeasureTheory.StronglyMeasurable.const_smul' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_left' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_left'' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_right' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_right'' +MeasureTheory.Submartingale.stoppedValue_leastGE_eLpNorm_le' +MeasureTheory.Subsingleton.aestronglyMeasurable' +MeasureTheory.Subsingleton.stronglyMeasurable' +MeasureTheory.TendstoInMeasure.congr' +MeasureTheory.TendstoInMeasure.exists_seq_tendsto_ae' +MeasureTheory.tendsto_sum_indicator_atTop_iff' +MeasureTheory.tilted_apply' +MeasureTheory.tilted_apply_eq_ofReal_integral' +MeasureTheory.tilted_const' +MeasureTheory.tilted_neg_same' +MeasureTheory.tilted_zero' +MeasureTheory.upcrossingsBefore_zero' +MeasureTheory.upperCrossingTime_stabilize' +MeasureTheory.upperCrossingTime_zero' +MeasureTheory.VectorMeasure.ext_iff' +MeasureTheory.VectorMeasure.le_iff' +MeasureTheory.weightedSMul_union' +MeasureTheory.withDensity_apply' +MeasureTheory.withDensity_apply_eq_zero' +MeasureTheory.withDensity_smul' +MeasureTheory.withDensityᵥ_add' +MeasureTheory.withDensityᵥ_neg' +MeasureTheory.withDensityᵥ_smul' +MeasureTheory.withDensityᵥ_smul_eq_withDensityᵥ_withDensity' +MeasureTheory.withDensityᵥ_sub' +MeasureTheory.zero_mem_ℒp' +mem_ball_iff_norm'' +mem_ball_iff_norm''' +mem_closedBall_iff_norm'' +mem_closedBall_iff_norm''' +mem_closure_iff_nhds' +mem_closure_iff_nhds_basis' +mem_coclosed_Lindelof' +mem_codiscrete' +mem_coLindelof' +memℓp_gen' +mem_nhds_prod_iff' +mem_pairSelfAdjointMatricesSubmodule' +mem_rootsOfUnity' +mem_rootsOfUnity_prime_pow_mul_iff' +mem_selfAdjointMatricesSubmodule' +mem_skewAdjointMatricesSubmodule' +mem_sphere_iff_norm' +Metric.ball_eq_ball' +Metric.ball_subset_ball' +Metric.closedBall_subset_ball' +Metric.closedBall_subset_closedBall' +Metric.closedBall_zero' +Metric.continuousAt_iff' +Metric.continuous_iff' +Metric.continuousOn_iff' +Metric.continuousWithinAt_iff' +Metric.cthickening_eq_iInter_cthickening' +Metric.cthickening_eq_iInter_thickening' +Metric.cthickening_eq_iInter_thickening'' +Metric.mem_ball' +Metric.mem_closedBall' +Metric.mem_of_closed' +Metric.mem_sphere' +midpoint_eq_iff' +min_def' +min_div_div_left' +min_div_div_right' +minimal_subset_iff' +min_inv_inv' +min_mul_distrib' +min_mul_min_le_min_mul_mul' +minpoly.dvd_map_of_isScalarTower' +minpoly.eq_X_sub_C' +minpoly.unique' +min_rec' +Miu.le_pow2_and_pow2_eq_mod3' +mk_eq_mk_of_basis' +Mod_.comp_hom' +Mod_.id_hom' +ModularCyclotomicCharacter.toFun_spec' +ModularCyclotomicCharacter.toFun_spec'' +ModularCyclotomicCharacter.toFun_unique' +Module.Baer.ExtensionOfMaxAdjoin.extendIdealTo_wd' +ModuleCat.CoextendScalars.smul_apply' +ModuleCat.hasLimits' +ModuleCat.restrictScalars.smul_def' +Module.End_algebraMap_isUnit_inv_apply_eq_iff' +Module.End.smulCommClass' +Module.free_of_finite_type_torsion_free' +Module.Free.of_subsingleton' +Module.mem_support_iff' +Module.not_mem_support_iff' +Module.projective_def' +Monad.mapM' +Monad.sequence' +Mon_.comp_hom' +Mon_.id_hom' +MonoidAlgebra.lift_apply' +MonoidAlgebra.lift_unique' +Monoid.CoprodI.lift_comp_of' +Monoid.CoprodI.lift_of' +Monoid.Coprod.induction_on' +Monoid.exponent_eq_iSup_orderOf' +Monoid.exponent_min' +MonoidHom.coe_toAdditive' +MonoidHom.coe_toAdditive'' +MonoidHom.comap_bot' +MonoidHom.map_zpow' +MonoidHom.prod_map_comap_prod' +Monoid.PushoutI.NormalWord.base_smul_def' +Monoid.PushoutI.NormalWord.summand_smul_def' +Monotone.const_mul' +Monotone.mul_const' +MonotoneOn.const_mul' +MonotoneOn.mul_const' +MulActionHom.comp_inverse' +MulActionHom.inverse_eq_inverse' +MulActionHom.inverse'_inverse' +MulAction.mem_fixedPoints' +MulAction.mem_stabilizer_finset' +MulAction.mem_stabilizer_set' +MulAction.orbitRel.quotient_eq_of_quotient_subgroup_eq' +MulAction.orbitRel.Quotient.mem_subgroup_orbit_iff' +MulAction.orbitZPowersEquiv_symm_apply' +MulAction.Quotient.coe_smul_out' +MulAction.Quotient.mk_smul_out' +MulAction.right_quotientAction' +MulChar.star_apply' +mul_div_assoc' +mul_div_cancel_of_imp' +mul_eq_mul_iff_eq_and_eq_of_pos' +mul_eq_of_eq_div' +mul_eq_one' +MulEquiv.mk_coe' +MulHom.prod_map_comap_prod' +mul_inv_le_iff' +mul_inv_le_iff_le_mul' +mul_inv_le_mul_inv_iff' +mul_inv_lt_iff' +mul_inv_lt_iff_le_mul' +mul_inv_lt_mul_inv_iff' +mul_invOf_cancel_left' +mul_invOf_cancel_right' +mul_invOf_self' +mul_left_cancel'' +mul_left_inj' +mul_le_iff_le_one_left' +mul_le_iff_le_one_right' +mul_le_mul' +mul_le_mul_left' +mul_le_mul_of_nonneg' +mul_le_mul_of_nonneg_of_nonpos' +mul_le_mul_of_nonpos_of_nonneg' +mul_le_mul_of_nonpos_of_nonpos' +mul_le_mul_right' +mul_le_of_le_of_le_one' +mul_le_of_le_one_left' +mul_le_of_le_one_of_le' +mul_le_of_le_one_right' +mul_lt_iff_lt_one_left' +mul_lt_iff_lt_one_right' +mul_lt_mul_left' +mul_lt_mul_of_pos' +mul_lt_mul_right' +mul_lt_of_le_of_lt_one' +mul_lt_of_le_one_of_lt' +mul_lt_of_lt_of_le_one' +mul_lt_of_lt_of_lt_one' +mul_lt_of_lt_one_left' +mul_lt_of_lt_one_of_le' +mul_lt_of_lt_one_of_lt' +mul_lt_of_lt_one_right' +mul_ne_one' +mul_right_cancel'' +mul_right_inj' +mul_rotate' +MulSemiringActionHom.coe_fn_coe' +MultilinearMap.mkContinuousLinear_norm_le' +MultilinearMap.mkContinuousMultilinear_norm_le' +Multipliable.sigma' +Multiplicative.isometricSMul' +Multiplicative.isometricVAdd'' +multiplicity.is_greatest' +multiplicity.mul' +multiplicity.pow' +multiplicity.unique' +Multiset.add_le_add_iff_left' +Multiset.aemeasurable_prod' +Multiset.aestronglyMeasurable_prod' +Multiset.antidiagonal_coe' +Multiset.attach_map_val' +Multiset.count_sum' +Multiset.dedup_subset' +Multiset.ext' +Multiset.extract_gcd' +Multiset.filter_attach' +Multiset.filter_eq' +Multiset.foldl_induction' +Multiset.foldr_induction' +Multiset.induction_on' +Multiset.map_const' +Multiset.map_filter' +Multiset.map_id' +Multiset.measurable_prod' +Multiset.Nat.antidiagonal_succ' +Multiset.Nat.antidiagonal_succ_succ' +Multiset.noncommProd_cons' +Multiset.powersetAux_perm_powersetAux' +Multiset.powersetCard_coe' +Multiset.powerset_coe' +Multiset.prod_hom' +Multiset.prod_lt_prod' +Multiset.prod_lt_prod_of_nonempty' +Multiset.prod_map_inv' +Multiset.prod_X_add_C_coeff' +Multiset.quot_mk_to_coe' +Multiset.quot_mk_to_coe'' +Multiset.revzip_powersetAux' +Multiset.revzip_powersetAux_perm_aux' +Multiset.smul_prod' +Multiset.stronglyMeasurable_prod' +Multiset.subset_dedup' +MvFunctor.f' +MvFunctor.g' +MvFunctor.id_map' +MvPFunctor.liftP_iff' +MvPFunctor.M.bisim' +MvPFunctor.M.dest_corec' +MvPFunctor.M.dest'_eq_dest' +MvPFunctor.M.dest_eq_dest' +MvPFunctor.wDest'_wMk' +MvPolynomial.aeval_zero' +MvPolynomial.algHom_ext' +MvPolynomial.C_mul' +MvPolynomial.coeff_monomial_mul' +MvPolynomial.coeff_mul_monomial' +MvPolynomial.coeff_mul_X' +MvPolynomial.coeff_X' +MvPolynomial.coeff_X_mul' +MvPolynomial.degrees_X' +MvPolynomial.eval₂_eq' +MvPolynomial.eval₂Hom_congr' +MvPolynomial.eval₂Hom_X' +MvPolynomial.eval₂Hom_zero' +MvPolynomial.eval_eq' +MvPolynomial.eval_eq_eval_mv_eval' +MvPolynomial.eval_zero' +MvPolynomial.finSuccEquiv_support' +MvPolynomial.homogeneousComponent_eq_zero' +MvPolynomial.isLocalization_C_mk' +MvPolynomial.monomial_zero' +MvPolynomial.support_esymm' +MvPolynomial.support_esymm'' +MvPolynomial.weightedHomogeneousComponent_eq_zero' +MvPowerSeries.algebraMap_apply' +MvPowerSeries.algebraMap_apply'' +MvPowerSeries.invOfUnit_eq' +MvQPF.Cofix.dest_corec' +MvQPF.liftR_map_last' +MvQPF.recF_eq' +MvQPF.wEquiv.abs' +Nat.add_descFactorial_eq_ascFactorial' +Nat.ascFactorial_eq_factorial_mul_choose' +Nat.bit_add' +Nat.card_eq_two_iff' +Nat.cauchy_induction' +Nat.choose_eq_asc_factorial_div_factorial' +Nat.choose_succ_succ' +Nat.coprime_of_dvd' +Nat.count_add' +Nat.count_succ' +Nat.decreasingInduction_succ' +Nat.digits_def' +Nat.digits_zero_succ' +Nat.dist_tri_left' +Nat.dist_tri_right' +Nat.div_add_mod' +Nat.div_le_of_le_mul' +Nat.div_le_self' +Nat.div_lt_iff_lt_mul' +Nat.dvd_sub' +Nat.eq_sqrt' +Nat.eq_sub_of_add_eq' +Nat.equivProdNatFactoredNumbers_apply' +Nat.equivProdNatSmoothNumbers_apply' +Nat.even_add' +Nat.even_or_odd' +Nat.even_pow' +Nat.even_sub' +Nat.even_xor_odd' +Nat.exists_mul_self' +Nat.factorial_inj' +Nat.find_min' +Nat.floor_eq_iff' +Nat.floor_eq_on_Ico' +Nat.floor_lt' +Nat.Icc_eq_range' +Nat.Ico_eq_range' +Nat.iInf_le_succ' +Nat.iInf_lt_succ' +Nat.Ioc_eq_range' +Nat.Ioo_eq_range' +Nat.iSup_le_succ' +Nat.iSup_lt_succ' +Nat.le_div_iff_mul_le' +Nat.le_floor_iff' +Nat.le_minFac' +Nat.le_nth_count' +Nat.leRecOn_succ' +Nat.leRec_succ' +Nat.le_sqrt' +Nat.log_eq_one_iff' +Nat.lt_sub_iff_add_lt' +Nat.lt_succ_sqrt' +Nat.mem_primeFactorsList' +Nat.mod_add_div' +Nat.ModEq.add_left_cancel' +Nat.ModEq.add_right_cancel' +Nat.ModEq.cancel_left_div_gcd' +Nat.ModEq.cancel_right_div_gcd' +Nat.modEq_list_prod_iff' +Nat.ModEq.mul_left' +Nat.ModEq.mul_left_cancel_iff' +Nat.ModEq.mul_right' +Nat.ModEq.mul_right_cancel_iff' +Nat.monotone_primeCounting' +Nat.mul_add_mod' +Nat.mul_div_cancel_left' +nat_mul_inj' +Nat.mul_lt_mul'' +Nat.not_exists_sq' +Nat.not_prime_mul' +Nat.nth_le_nth' +Nat.nth_lt_nth' +Nat.odd_add' +Nat.odd_sub' +Nat.ofDigits_modEq' +Nat.ofDigits_zmodeq' +Nat.one_le_pow' +Nat.one_lt_pow' +Nat.one_lt_two_pow' +Nat.pair_unpair' +Nat.Partrec.Code.encode_lt_rfind' +Nat.Partrec.Code.rec_prim' +Nat.Partrec'.comp' +Nat.Partrec.merge' +Nat.Partrec.prec' +Nat.Partrec.rfind' +Nat.pow_lt_ascFactorial' +Nat.pow_sub_lt_descFactorial' +Nat.prime_def_lt' +Nat.prime_def_lt'' +Nat.Prime.eq_two_or_odd' +Nat.primeFactorsList_chain' +Nat.Prime.not_prime_pow' +Nat.Prime.one_lt' +Nat.Primrec.casesOn' +Nat.Primrec'.comp' +Nat.Primrec'.prec' +Nat.Primrec.swap' +Nat.prod_divisorsAntidiagonal' +Nat.rfind_dom' +Nat.rfind_min' +Nat.sInf_add' +Nat.size_shiftLeft' +Nat.sq_mul_squarefree_of_pos' +Nat.sqrt_add_eq' +Nat.sqrt_eq' +Nat.sqrt_le' +Nat.sqrt_lt' +Nat.sqrt_mul_sqrt_lt_succ' +Nat.sub_eq_of_eq_add' +Nat.sub_lt_iff_lt_add' +Nat.succ_le_succ_sqrt' +Nat.succ_pos' +Nat.sum_totient' +Nat.surjective_primeCounting' +Nat.tendsto_primeCounting' +Nat.uIcc_eq_range' +Ne.bot_lt' +neg_div' +neg_gcd' +neg_of_smul_neg_left' +neg_of_smul_neg_right' +neg_pow' +Ne.lt_of_le' +Ne.lt_top' +ne_of_irrefl' +ne_of_ne_of_eq' +newton_seq_dist_tendsto' +NeZero.ne' +NeZero.of_gt' +ne_zero_of_irreducible_X_pow_sub_C' +nhds_basis_Ioo' +nhds_basis_uniformity' +nhds_def' +nhds_eq_comap_uniformity' +nhds_eq_uniformity' +nhds_left'_sup_nhds_right' +nhds_left_sup_nhds_right' +nhds_one_symm' +nhdsWithin_eq_nhdsWithin' +nhdsWithin_extChartAt_target_eq' +nhdsWithin_Ici_basis' +nhdsWithin_Ici_eq' +nhdsWithin_Ici_eq'' +nhdsWithin_Iic_basis' +nhdsWithin_Iic_eq' +nhdsWithin_Iic_eq'' +nhdsWithin_Iio_basis' +nhdsWithin_Iio_neBot' +nhdsWithin_Iio_self_neBot' +nhdsWithin_inter' +nhdsWithin_inter_of_mem' +nhdsWithin_Ioi_basis' +nhdsWithin_Ioi_neBot' +nhdsWithin_Ioi_self_neBot' +nhdsWithin_pi_eq' +nhdsWithin_restrict' +nhdsWithin_restrict'' +nndist_eq_nnnorm_vsub' +nndist_midpoint_midpoint_le' +nndist_nnnorm_nnnorm_le' +nnnorm_algebraMap' +nnnorm_eq_zero' +nnnorm_inv' +nnnorm_le_nnnorm_add_nnnorm_div' +nnnorm_le_pi_nnnorm' +nnnorm_mul_le' +nnnorm_ne_zero_iff' +nnnorm_one' +nnnorm_pos' +NNRat.instSMulCommClass' +NNReal.ball_zero_eq_Ico' +NNReal.closedBall_zero_eq_Icc' +NNReal.div_le_iff' +NNReal.div_le_of_le_mul' +NNReal.div_lt_iff' +NNReal.inner_le_Lp_mul_Lq_tsum' +NNReal.le_div_iff' +NNReal.list_prod_map_rpow' +NNReal.Lp_add_le_tsum' +NNReal.lt_div_iff' +NNReal.nndist_zero_eq_val' +NNReal.rpow_add' +NNReal.rpow_add_intCast' +NNReal.rpow_add_natCast' +NNReal.rpow_add_one' +NNReal.rpow_one_add' +NNReal.rpow_one_sub' +NNReal.rpow_sub' +NNReal.rpow_sub_intCast' +NNReal.rpow_sub_natCast' +NNReal.rpow_sub_one' +NNReal.tendsto_coe' +NonUnitalAlgHom.coe_inverse' +NonUnitalAlgHom.coe_restrictScalars' +NonUnitalStarAlgebra.adjoin_induction' +NonUnitalStarAlgHom.coe_mk' +NonUnitalStarAlgHom.coe_restrictScalars' +NonUnitalStarSubalgebra.instIsScalarTower' +NonUnitalStarSubalgebra.instSMulCommClass' +NonUnitalStarSubalgebra.module' +NonUnitalSubalgebra.instIsScalarTower' +NonUnitalSubalgebra.instModule' +NonUnitalSubalgebra.instSMulCommClass' +NonUnitalSubring.coe_mk' +NonUnitalSubring.eq_top_iff' +NonUnitalSubring.mem_mk' +NonUnitalSubsemiring.coe_mk' +NonUnitalSubsemiring.eq_top_iff' +NonUnitalSubsemiring.mem_mk' +normalClosure_eq_iSup_adjoin' +norm_algebraMap' +NormedAddCommGroup.cauchy_series_of_le_geometric' +NormedAddCommGroup.cauchy_series_of_le_geometric'' +NormedAddGroupHom.coe_mkNormedAddGroupHom' +NormedAddGroupHom.completion_coe' +NormedAddGroupHom.norm_comp_le_of_le' +NormedRing.inverse_one_sub_nth_order' +NormedSpace.exp_conj' +NormedSpace.expSeries_apply_eq' +NormedSpace.expSeries_apply_eq_div' +NormedSpace.exp_series_hasSum_exp' +NormedSpace.expSeries_hasSum_exp_of_mem_ball' +NormedSpace.expSeries_summable' +NormedSpace.expSeries_summable_of_mem_ball' +NormedSpace.exp_units_conj' +NormedSpace.isVonNBounded_iff' +NormedSpace.norm_expSeries_summable' +NormedSpace.norm_expSeries_summable_of_mem_ball' +norm_eq_of_mem_sphere' +norm_eq_zero'' +norm_eq_zero''' +norm_inv' +norm_le_norm_add_const_of_dist_le' +norm_le_norm_add_norm_div' +norm_le_of_mem_closedBall' +norm_le_pi_norm' +norm_le_zero_iff'' +norm_le_zero_iff''' +norm_lt_of_mem_ball' +norm_ne_zero_iff' +norm_nonneg' +norm_of_subsingleton' +norm_one' +norm_pos_iff'' +norm_pos_iff''' +norm_sub_norm_le' +norm_toNNReal' +not_dvd_index_sylow' +not_lt_zero' +not_mem_of_lt_csInf' +npow_mul' +nsmul_eq_mul' +nullMeasurableSet_lt' +Num.add_ofNat' +NumberField.InfinitePlace.orbitRelEquiv_apply_mk'' +NumberField.mixedEmbedding.convexBodySumFun_apply' +NumberField.mixedEmbedding.norm_eq_zero_iff' +NumberField.Units.regulator_eq_det' +Num.cast_sub' +Num.cast_succ' +Num.cast_zero' +Num.mem_ofZNum' +Num.of_to_nat' +Num.succ_ofInt' +odd_add_one_self' +odd_add_self_one' +ofReal_norm_eq_coe_nnnorm' +OmegaCompletePartialOrder.const_continuous' +OmegaCompletePartialOrder.ContinuousHom.bind_continuous' +OmegaCompletePartialOrder.ContinuousHom.forall_forall_merge' +OmegaCompletePartialOrder.ContinuousHom.ite_continuous' +OmegaCompletePartialOrder.ContinuousHom.map_continuous' +OmegaCompletePartialOrder.ContinuousHom.seq_continuous' +OmegaCompletePartialOrder.Continuous.of_bundled' +OmegaCompletePartialOrder.flip₁_continuous' +OmegaCompletePartialOrder.flip₂_continuous' +OmegaCompletePartialOrder.id_continuous' +OmegaCompletePartialOrder.ScottContinuous.continuous' +one_le_div' +one_le_finprod' +one_le_pow_of_one_le' +one_le_thickenedIndicator_apply' +one_le_two' +one_lt_div' +one_lt_finprod' +one_lt_pow' +one_lt_zpow' +one_ne_zero' +OnePoint.continuousAt_infty' +OnePoint.isOpen_iff_of_mem' +OnePoint.tendsto_nhds_infty' +ONote.exists_lt_mul_omega' +ONote.exists_lt_omega_opow' +ONote.fastGrowing_zero' +ONote.NF.below_of_lt' +ONote.nf_repr_split' +ONote.NF.snd' +ONote.split_eq_scale_split' +OpenEmbedding.tendsto_nhds_iff' +openSegment_eq_image' +openSegment_eq_Ioo' +Option.bind_congr' +Option.bind_eq_bind' +Option.bind_eq_some' +Option.guard_eq_some' +Option.map_bind' +Option.map_coe' +Option.none_bind' +Option.none_orElse' +Option.orElse_eq_none' +Option.orElse_eq_some' +Option.orElse_none' +Option.some_bind' +Option.some_orElse' +or_congr_left' +or_congr_right' +OrderDual.continuousConstSMul' +OrderDual.instDistribMulAction' +OrderDual.instDistribSMul' +OrderDual.instIsScalarTower' +OrderDual.instIsScalarTower'' +OrderDual.instModule' +OrderDual.instMulAction' +OrderDual.instMulActionWithZero' +OrderDual.instPow' +OrderDual.instSMulCommClass' +OrderDual.instSMulCommClass'' +OrderDual.instSMulWithZero' +Order.height_le_iff' +Order.Ideal.IsMaximal.isCoatom' +OrderIso.isGLB_image' +OrderIso.isGLB_preimage' +OrderIso.isLUB_image' +OrderIso.isLUB_preimage' +OrderIso.map_bot' +OrderIso.map_csInf' +OrderIso.map_csSup' +OrderIso.map_top' +OrderIso.subsingleton_of_wellFoundedGT' +OrderIso.subsingleton_of_wellFoundedLT' +Order.isPredPrelimitRecOn_pred' +Order.isSuccPrelimitRecOn_succ' +Order.not_isPredPrelimit_iff' +Order.not_isSuccPrelimit_iff' +orderOf_eq_zero_iff' +orderOf_pow' +Ordinal.add_lt_add_iff_left' +Ordinal.blsub_eq_lsub' +Ordinal.brange_bfamilyOfFamily' +Ordinal.bsup_eq_sup' +Ordinal.cof_eq' +Ordinal.comp_bfamilyOfFamily' +Ordinal.comp_familyOfBFamily' +Ordinal.enum_le_enum' +Ordinal.enum_zero_le' +Ordinal.IsNormal.le_set' +Ordinal.lift_down' +Ordinal.lift.principalSeg_top' +Ordinal.liftPrincipalSeg_top' +Ordinal.lsub_eq_blsub' +Ordinal.lt_nmul_iff₃' +Ordinal.mul_eq_zero' +Ordinal.nhds_right' +Ordinal.nmul_le_iff₃' +Ordinal.nmul_nadd_le₃' +Ordinal.nmul_nadd_lt₃' +Ordinal.pred_eq_iff_not_succ' +Ordinal.range_familyOfBFamily' +Ordinal.relIso_enum' +Ordinal.succ_le_iff' +Ordinal.sup_eq_bsup' +Ordinal.toPGame_moveLeft' +Ordinal.type_def' +Ordinal.typein_le_typein' +Ordinal.type_le_iff' +Ordinal.zero_opow' +Ordnode.all_balance' +Ordnode.all_node' +Ordnode.balance_eq_balance' +Ordnode.balanceL_eq_balance' +Ordnode.balanceR_eq_balance' +Ordnode.dual_balance' +Ordnode.dual_node' +Ordnode.length_toList' +Ordnode.Raised.dist_le' +Ordnode.size_balance' +Ordnode.Sized.balance' +Ordnode.Sized.eq_node' +Ordnode.Sized.node' +Ordnode.Valid'.balance' +Ordnode.Valid'.node' +OreLocalization.add' +OreLocalization.add'' +OreLocalization.div_eq_one' +OreLocalization.inv' +OreLocalization.mul_cancel' +OreLocalization.oreDiv_add_char' +OreLocalization.smul' +OreLocalization.smul_cancel' +OreLocalization.zero_oreDiv' +Orientation.inner_rightAngleRotation_swap' +Orientation.kahler_comp_rightAngleRotation' +Orientation.rightAngleRotation_map' +Orientation.volumeForm_robust' +Padic.complete' +Padic.complete'' +Padic.lim' +padicNormE.eq_padic_norm' +padicNormE.image' +padicNorm.sum_le' +padicNorm.sum_lt' +Padic.rat_dense' +padicValNat_def' +padicValNat.div' +PartENat.casesOn' +PartENat.get_natCast' +PartENat.get_ofNat' +PartENat.toWithTop_natCast' +PartENat.toWithTop_one' +PartENat.toWithTop_top' +PartENat.toWithTop_zero' +Part.eq_none_iff' +Part.Fix.approx_mono' +Part.fix_def' +PartialEquiv.image_source_inter_eq' +PartialEquiv.symm_image_target_inter_eq' +PartialEquiv.trans_refl_restr' +PartialEquiv.trans_source' +PartialEquiv.trans_source'' +PartialEquiv.trans_target' +PartialEquiv.trans_target'' +PartialHomeomorph.contDiffWithinAt_extend_coord_change' +PartialHomeomorph.continuousAt_extend_symm' +PartialHomeomorph.eventually_left_inverse' +PartialHomeomorph.eventually_nhds' +PartialHomeomorph.eventually_nhdsWithin' +PartialHomeomorph.eventually_right_inverse' +PartialHomeomorph.extend_coord_change_source_mem_nhdsWithin' +PartialHomeomorph.extend_target' +PartialHomeomorph.image_source_inter_eq' +PartialHomeomorph.IsImage.iff_preimage_eq' +PartialHomeomorph.IsImage.iff_symm_preimage_eq' +PartialHomeomorph.isOpen_extend_preimage' +PartialHomeomorph.ofSet_trans' +PartialHomeomorph.prod_eq_prod_of_nonempty' +PartialHomeomorph.restr_source' +PartialHomeomorph.restr_toPartialEquiv' +PartialHomeomorph.trans_of_set' +PartialHomeomorph.trans_source' +PartialHomeomorph.trans_source'' +PartialHomeomorph.trans_target' +PartialHomeomorph.trans_target'' +PartitionOfUnity.exists_finset_nhd' +PartitionOfUnity.sum_finsupport' +Part.map_id' +Partrec₂.unpaired' +Partrec.const' +Partrec.merge' +PathConnectedSpace.exists_path_through_family' +Path.extend_extends' +pcontinuous_iff' +Pell.eq_of_xn_modEq' +Perfection.coeff_iterate_frobenius' +Perfection.coeff_pow_p' +PerfectionMap.comp_equiv' +PerfectionMap.comp_symm_equiv' +PFunctor.Approx.head_succ' +PFunctor.liftp_iff' +PFunctor.M.agree_iff_agree' +PFunctor.M.bisim' +PFunctor.M.casesOn_mk' +PFunctor.M.ext' +PFunctor.M.head_eq_head' +PFunctor.M.isPath_cons' +Pi.compact_Icc_space' +Pi.continuous_postcomp' +Pi.continuous_precomp' +Pi.cstarRing' +Pi.distribMulAction' +Pi.distribSMul' +pi_Icc_mem_nhds' +pi_Ici_mem_nhds' +pi_Ico_mem_nhds' +pi_Iic_mem_nhds' +pi_Iio_mem_nhds' +Pi.induced_precomp' +Pi.infConvergenceClass' +Pi.instBoundedSMul' +pi_Ioc_mem_nhds' +pi_Ioi_mem_nhds' +pi_Ioo_mem_nhds' +Pi.isometricSMul' +Pi.isometricSMul'' +Pi.isScalarTower' +Pi.isScalarTower'' +Pi.lawfulFix' +Pi.Lex.noMaxOrder' +Pi.module' +Pi.mulAction' +Pi.mulActionWithZero' +Pi.mulDistribMulAction' +pinGroup.star_eq_inv' +pi_nnnorm_const' +pi_nnnorm_const_le' +Pi.nnnorm_def' +pi_nnnorm_le_iff' +pi_nnnorm_lt_iff' +pi_norm_const' +pi_norm_const_le' +Pi.norm_def' +pi_norm_le_iff_of_nonempty' +Pi.orderClosedTopology' +Pi.smul' +Pi.smul_apply' +Pi.smulCommClass' +Pi.smulCommClass'' +Pi.smul_def' +Pi.smulWithZero' +Pi.smulZeroClass' +PiSubtype.canLift' +Pi.supConvergenceClass' +PiTensorProduct.add_tprodCoeff' +PiTensorProduct.distribMulAction' +PiTensorProduct.hasSMul' +PiTensorProduct.isScalarTower' +PiTensorProduct.lift.unique' +PiTensorProduct.module' +PiTensorProduct.smulCommClass' +PiTensorProduct.smul_tprodCoeff' +PiTensorProduct.zero_tprodCoeff' +Pi.uniformContinuous_postcomp' +Pi.uniformContinuous_precomp' +Pi.uniformSpace_comap_precomp' +PNat.coe_toPNat' +PNat.div_add_mod' +PNat.dvd_iff' +PNat.factorMultiset_le_iff' +PNat.find_min' +PNat.gcd_rel_left' +PNat.gcd_rel_right' +PNat.mod_add_div' +PNat.XgcdType.reduce_isReduced' +PNat.XgcdType.reduce_isSpecial' +pNilradical_eq_bot' +Pointed.Hom.comp_toFun' +Pointed.Hom.id_toFun' +Polynomial.add' +Polynomial.addHom_ext' +Polynomial.aeval_apply_smul_mem_of_le_comap' +Polynomial.aeval_eq_sum_range' +Polynomial.as_sum_range' +Polynomial.card_roots' +Polynomial.card_roots_sub_C' +Polynomial.card_support_eq' +Polynomial.card_support_eraseLead' +Polynomial.C_mul' +Polynomial.coeff_expand_mul' +Polynomial.coeff_mul_X_pow' +Polynomial.coeff_restriction' +Polynomial.coeff_toSubring' +Polynomial.coeff_X_pow_mul' +Polynomial.coeff_zero_eq_aeval_zero' +Polynomial.degree_eq_card_roots' +Polynomial.degree_mul' +Polynomial.degree_pow' +Polynomial.div_tendsto_atBot_of_degree_gt' +Polynomial.div_tendsto_atTop_of_degree_gt' +Polynomial.eq_zero_of_natDegree_lt_card_of_eval_eq_zero' +Polynomial.eval₂_comp' +Polynomial.eval₂_eq_sum_range' +Polynomial.eval₂_mul' +Polynomial.eval₂_mul_C' +Polynomial.eval₂_pow' +Polynomial.eval_eq_sum_range' +Polynomial.eval_smul' +Polynomial.exists_root_of_splits' +Polynomial.expand_contract' +Polynomial.hasseDeriv_one' +Polynomial.hasseDeriv_zero' +Polynomial.HasSeparableContraction.dvd_degree' +Polynomial.hermite_eq_deriv_gaussian' +Polynomial.isRoot_cyclotomic_iff' +Polynomial.isUnit_iff' +Polynomial.isUnitTrinomial_iff' +Polynomial.isUnitTrinomial_iff'' +Polynomial.leadingCoeff_add_of_degree_lt' +Polynomial.leadingCoeff_map' +Polynomial.leadingCoeff_mul' +Polynomial.leadingCoeff_pow' +Polynomial.leadingCoeff_sub_of_degree_lt' +Polynomial.lhom_ext' +Polynomial.lt_rootMultiplicity_iff_isRoot_iterate_derivative_of_mem_nonZeroDivisors' +Polynomial.lt_rootMultiplicity_of_isRoot_iterate_derivative_of_mem_nonZeroDivisors' +Polynomial.map_dvd_map' +Polynomial.map_rootOfSplits' +Polynomial.mem_aroots' +Polynomial.mem_roots' +Polynomial.mem_rootSet' +Polynomial.mem_roots_sub_C' +Polynomial.mkDerivation_one_eq_derivative' +PolynomialModule.eval_map' +PolynomialModule.isScalarTower' +Polynomial.Monic.geom_sum' +Polynomial.Monic.irreducible_iff_natDegree' +Polynomial.Monic.natDegree_mul' +Polynomial.monic_zero_iff_subsingleton' +Polynomial.mul' +Polynomial.mul_scaleRoots' +Polynomial.natDegree_eq_card_roots' +Polynomial.natDegree_eq_support_max' +Polynomial.natDegree_mul' +Polynomial.natDegree_pow' +Polynomial.natDegree_removeFactor' +Polynomial.natTrailingDegree_eq_support_min' +Polynomial.natTrailingDegree_mul' +Polynomial.neg' +Polynomial.ringHom_ext' +Polynomial.rootMultiplicity_eq_natTrailingDegree' +Polynomial.rootMultiplicity_mul' +Polynomial.rootMultiplicity_pos' +Polynomial.rootSet_maps_to' +Polynomial.roots_ne_zero_of_splits' +Polynomial.scaleRoots_dvd' +Polynomial.separable_def' +Polynomial.Separable.of_pow' +Polynomial.separable_prod' +Polynomial.separable_prod_X_sub_C_iff' +polynomial_smul_apply' +Polynomial.splits_of_splits_mul' +Polynomial.SplittingField.algebra' +Polynomial.SplittingFieldAux.algebra' +Polynomial.SplittingFieldAux.algebra'' +Polynomial.SplittingFieldAux.algebra''' +Polynomial.SplittingFieldAux.scalar_tower' +Polynomial.sum_add' +Polynomial.sum_smul_index' +Polynomial.support_binomial' +Polynomial.support_C_mul_X' +Polynomial.support_C_mul_X_pow' +Polynomial.support_monomial' +Polynomial.support_trinomial' +Polynomial.taylor_zero' +Polynomial.trailingDegree_mul' +Polynomial.trinomial_leading_coeff' +Polynomial.trinomial_trailing_coeff' +PosNum.cast_one' +PosNum.cast_sub' +PosNum.of_to_nat' +PosNum.one_sub' +PosNum.pred'_succ' +PosNum.succ'_pred' +pow_add_pow_le' +pow_card_eq_one' +pow_eq_zero_iff' +PowerBasis.exists_eq_aeval' +PowerBasis.mem_span_pow' +PowerSeries.algebraMap_apply' +PowerSeries.algebraMap_apply'' +PowerSeries.algebraPolynomial' +PowerSeries.coeff_mul_X_pow' +PowerSeries.coeff_X_pow_mul' +PowerSeries.derivative_inv' +PowerSeries.invOfUnit_eq' +PowerSeries.trunc_derivative' +PowerSeries.trunc_zero' +pow_le_one' +pow_le_pow_iff_right' +pow_le_pow_left' +pow_le_pow_right' +pow_le_pow_right_of_le_one' +pow_lt_one' +pow_lt_pow_iff_right' +pow_lt_pow_left' +pow_lt_pow_right' +pow_mul' +pow_mul_comm' +pow_right_strictMono' +pow_succ' +pow_three' +ppow_mul' +PProd.exists' +PProd.forall' +PredOrder.prelimitRecOn_pred' +preimage_nhdsWithin_coinduced' +PresheafOfModules.sheafificationHomEquiv_hom' +Pretrivialization.apply_symm_apply' +Pretrivialization.coe_fst' +Pretrivialization.continuousLinearMap_symm_apply' +Pretrivialization.ext' +Pretrivialization.mk_proj_snd' +Pretrivialization.proj_symm_apply' +PrimeMultiset.prod_dvd_iff' +PrimeSpectrum.iSup_basicOpen_eq_top_iff' +Primrec₂.nat_iff' +Primrec₂.unpaired' +Primrec.nat_casesOn' +Primrec.nat_omega_rec' +Primrec.nat_rec' +Primrec.vector_get' +Primrec.vector_ofFn' +PrincipalSeg.coe_coe_fn' +ProbabilityTheory.centralMoment_one' +ProbabilityTheory.cgf_const' +ProbabilityTheory.cgf_zero' +ProbabilityTheory.cond_apply' +ProbabilityTheory.cond_cond_eq_cond_inter' +ProbabilityTheory.condCount_inter' +ProbabilityTheory.condexp_ae_eq_integral_condexpKernel' +ProbabilityTheory.condexpKernel_ae_eq_condexp' +ProbabilityTheory.CondIndepSets.condIndep' +ProbabilityTheory.cond_mul_eq_inter' +ProbabilityTheory.evariance_def' +ProbabilityTheory.gaussianReal_absolutelyContinuous' +ProbabilityTheory.hasFiniteIntegral_compProd_iff' +ProbabilityTheory.iIndep.iIndepSets' +ProbabilityTheory.IndepFun.integral_mul' +ProbabilityTheory.IndepFun.mgf_add' +ProbabilityTheory.IndepSets.indep' +ProbabilityTheory.IsMarkovKernel.is_probability_measure' +ProbabilityTheory.IsMeasurableRatCDF.stieltjesFunctionAux_def' +ProbabilityTheory.Kernel.borelMarkovFromReal_apply' +ProbabilityTheory.Kernel.comap_apply' +ProbabilityTheory.Kernel.comap_id' +ProbabilityTheory.Kernel.comapRight_apply' +ProbabilityTheory.Kernel.comp_apply' +ProbabilityTheory.Kernel.const_comp' +ProbabilityTheory.Kernel.deterministic_apply' +ProbabilityTheory.Kernel.ext_iff' +ProbabilityTheory.Kernel.finset_sum_apply' +ProbabilityTheory.Kernel.fst_apply' +ProbabilityTheory.Kernel.iIndep.iIndepSets' +ProbabilityTheory.Kernel.IndepSets.indep' +ProbabilityTheory.Kernel.integral_deterministic' +ProbabilityTheory.Kernel.integral_integral_add' +ProbabilityTheory.Kernel.integral_integral_sub' +ProbabilityTheory.Kernel.lintegral_deterministic' +ProbabilityTheory.Kernel.map_apply' +ProbabilityTheory.Kernel.map_id' +ProbabilityTheory.Kernel.measurable_kernel_prod_mk_left' +ProbabilityTheory.Kernel.measure_eq_zero_or_one_of_indepSet_self' +ProbabilityTheory.Kernel.piecewise_apply' +ProbabilityTheory.Kernel.prod_apply' +ProbabilityTheory.Kernel.prodMkLeft_apply' +ProbabilityTheory.Kernel.prodMkRight_apply' +ProbabilityTheory.Kernel.restrict_apply' +ProbabilityTheory.Kernel.rnDeriv_def' +ProbabilityTheory.Kernel.rnDeriv_eq_top_iff' +ProbabilityTheory.Kernel.setIntegral_deterministic' +ProbabilityTheory.Kernel.setLIntegral_deterministic' +ProbabilityTheory.Kernel.snd_apply' +ProbabilityTheory.Kernel.sum_apply' +ProbabilityTheory.Kernel.swapLeft_apply' +ProbabilityTheory.Kernel.swapRight_apply' +ProbabilityTheory.Kernel.withDensity_apply' +ProbabilityTheory.Kernel.withDensity_one' +ProbabilityTheory.Kernel.withDensity_zero' +ProbabilityTheory.lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' +ProbabilityTheory.measurable_preCDF' +ProbabilityTheory.mgf_const' +ProbabilityTheory.mgf_pos' +ProbabilityTheory.mgf_zero' +ProbabilityTheory.variance_def' +ProbabilityTheory.variance_smul' +Prod.exists' +Prod.forall' +Prod.isometricSMul' +Prod.isometricSMul'' +Prod.map_apply' +Prod.map_fst' +Prod.map_id' +Prod.map_snd' +prod_mul_tprod_nat_mul' +Profinite.NobelingProof.coe_πs' +Profinite.NobelingProof.contained_C' +Profinite.NobelingProof.injective_πs' +Profinite.NobelingProof.Products.eval_πs' +Profinite.NobelingProof.Products.eval_πs_image' +Profinite.NobelingProof.Products.max_eq_o_cons_tail' +Projectivization.submodule_mk'' +Prop.countable' +QPF.Cofix.bisim' +QPF.liftp_iff' +QPF.recF_eq' +QPF.Wequiv.abs' +quadraticChar_eq_pow_of_char_ne_two' +QuadraticForm.equivalent_weightedSumSquares_units_of_nondegenerate' +QuadraticForm.posDef_of_toMatrix' +QuadraticForm.posDef_toMatrix' +QuadraticMap.isSymm_toMatrix' +QuadraticMap.map_sum' +quasiIsoAt_iff' +quasiIsoAt_iff_exactAt' +QuaternionAlgebra.self_add_star' +QuaternionAlgebra.star_add_self' +Quaternion.normSq_def' +Quaternion.self_add_star' +Quaternion.star_add_self' +Quiver.Hom.unop_op' +Quiver.Path.comp_inj' +QuotientAddGroup.btw_coe_iff' +Quotient.eq' +Quotient.eq'' +Quotient.exact' +QuotientGroup.coe_mk' +QuotientGroup.congr_mk' +QuotientGroup.kerLift_mk' +QuotientGroup.ker_mk' +QuotientGroup.lift_mk' +QuotientGroup.map_mk' +QuotientGroup.mk'_eq_mk' +QuotientGroup.out_eq' +Quotient.hrecOn₂'_mk'' +Quotient.hrecOn'_mk'' +Quotient.liftOn₂'_mk'' +Quotient.liftOn'_mk'' +Quotient.map₂'_mk'' +Quotient.map'_mk'' +quotientMap_quotient_mk' +Quotient.mk_out' +Quotient.out_eq' +Quotient.sound' +Quotient.surjective_liftOn' +range_pow_padicValNat_subset_divisors' +rank_finsupp' +rank_fun' +rank_lt_rank_dual' +Rat.add_def'' +Rat.add_num_den' +Rat.cast_mk' +Rat.div_def' +Rat.divInt_mul_divInt' +Rat.divInt_self' +Rat.floor_def' +RatFunc.liftAlgHom_apply_div' +RatFunc.liftMonoidWithZeroHom_apply_div' +RatFunc.liftRingHom_apply_div' +RatFunc.mk_eq_div' +RatFunc.mk_eq_mk' +RatFunc.mk_one' +RatFunc.num_div' +RatFunc.ofFractionRing_mk' +Rat.instSMulCommClass' +Rat.inv_def' +Rat.inv_divInt' +Rat.le_toNNRat_iff_coe_le' +Rat.mk'_mul_mk' +Rat.mul_num_den' +Rat.normalize_eq_mk' +Rat.sub_def'' +Rat.substr_num_den' +Rat.toNNRat_div' +Rat.toNNRat_lt_toNNRat_iff' +RCLike.hasSum_conj' +RCLike.I_im' +RCLike.normSq_eq_def' +RCLike.zero_re' +Real.arcsin_le_iff_le_sin' +Real.arcsin_lt_iff_lt_sin' +Real.arcsin_sin' +Real.binEntropy_eq_negMulLog_add_negMulLog_one_sub' +Real.b_ne_one' +Real.coe_toNNReal' +Real.continuousAt_const_rpow' +Real.continuous_log' +Real.cosh_sq' +Real.cos_sq' +Real.cos_two_mul' +Real.deriv_cos' +Real.deriv_log' +Real.deriv_rpow_const' +Real.eulerMascheroniConstant_lt_eulerMascheroniSeq' +Real.eulerMascheroniSeq_lt_eulerMascheroniSeq' +Real.exp_approx_end' +Real.exp_bound' +Real.exp_bound_div_one_sub_of_interval' +Real.fourierIntegral_continuousLinearMap_apply' +Real.fourierIntegral_continuousMultilinearMap_apply' +Real.fourierIntegral_eq' +Real.fourierIntegralInv_eq' +Real.hasDerivAt_arctan' +Real.inner_le_Lp_mul_Lq_tsum_of_nonneg' +Real.le_arcsin_iff_sin_le' +Real.le_def' +Real.le_sqrt' +Real.le_toNNReal_iff_coe_le' +Real.list_prod_map_rpow' +Real.logb_nonpos_iff' +Real.log_nonpos_iff' +Real.Lp_add_le_tsum_of_nonneg' +Real.lt_arcsin_iff_sin_lt' +Real.natCastle_toNNReal' +Real.nndist_eq' +Real.rpow_add' +Real.rpow_add_intCast' +Real.rpow_add_natCast' +Real.rpow_add_one' +Real.rpow_le_rpow_of_exponent_ge' +Real.rpow_lt_one_iff' +Real.rpow_one_add' +Real.rpow_one_sub' +Real.rpow_sub' +Real.rpow_sub_intCast' +Real.rpow_sub_natCast' +Real.rpow_sub_one' +Real.sin_arcsin' +Real.sqrt_div' +Real.sqrt_div_self' +Real.sqrt_eq_zero' +Real.sqrt_le_sqrt_iff' +Real.sqrt_lt' +Real.sqrt_mul' +Real.sqrt_ne_zero' +Real.strictAnti_eulerMascheroniSeq' +Real.surjOn_log' +Real.surjOn_logb' +Real.tan_add' +Real.tan_eq_zero_iff' +Real.tendsto_eulerMascheroniSeq' +Real.tendsto_integral_gaussian_smul' +Real.toNNReal_div' +Real.toNNReal_le_toNNReal_iff' +Real.toNNReal_lt_natCast' +Real.toNNReal_lt_toNNReal_iff' +RegularExpression.rmatch_iff_matches' +Relation.ReflTransGen.lift' +Relation.TransGen.closed' +Relation.TransGen.head' +Relation.TransGen.lift' +Relation.TransGen.tail' +RelSeries.last_snoc' +RelSeries.toList_chain' +RightOrdContinuous.map_sInf' +Ring.choose_one_right' +Ring.choose_zero_right' +RingCon.smulCommClass' +RingEquiv.mk_coe' +RingHom.eq_intCast' +RingHom.surjectiveOnStalks_iff_forall_maximal' +Ring.inverse_eq_inv' +Ring.mul_inverse_rev' +Ring.multichoose_one_right' +Ring.multichoose_zero_right' +RingQuot.ringQuot_ext' +RingTheory.Sequence.IsRegular.cons' +RingTheory.Sequence.isRegular_cons_iff' +RingTheory.Sequence.isWeaklyRegular_append_iff' +RingTheory.Sequence.IsWeaklyRegular.cons' +RingTheory.Sequence.isWeaklyRegular_cons_iff' +RootPairing.coroot_eq_coreflection_of_root_eq' +RootPairing.ne_zero' +rootsOfUnity.integer_power_of_ringEquiv' +root_X_pow_sub_C_ne_zero' +SameRay.of_subsingleton' +schnirelmannDensity_congr' +sdiff_eq_self_iff_disjoint' +sdiff_le' +sdiff_le_iff' +sdiff_sdiff_left' +sdiff_sdiff_right' +sdiff_sdiff_sup_sdiff' +sdiff_sup_self' +sdiff_symmDiff' +segment_eq_Icc' +segment_eq_image' +Semigroup.opposite_smulCommClass' +Seminorm.ball_finset_sup' +Seminorm.ball_zero' +Seminorm.closedBall_finset_sup' +Seminorm.closedBall_zero' +Seminorm.coe_sSup_eq' +Seminorm.continuous' +Seminorm.continuousAt_zero' +Seminorm.uniformContinuous' +Semiquot.blur_eq_blur' +Semiquot.mem_blur' +Semiquot.mem_pure' +SeparationQuotient.uniformContinuous_lift' +Set.biInter_and' +Set.biInter_finsetSigma' +Set.biInter_le_succ' +Set.biInter_lt_succ' +Set.biInter_sigma' +Set.bijOn_of_subsingleton' +Set.biUnion_and' +Set.biUnion_finsetSigma' +Set.biUnion_finsetSigma_univ' +Set.biUnion_le_succ' +Set.biUnion_lt_succ' +Set.biUnion_sigma' +SetCoe.exists' +SetCoe.forall' +Set.empty_card' +Set.encard_exchange' +Set.eq_of_mem_uIcc_of_mem_uIcc' +Set.eq_of_mem_uIoc_of_mem_uIoc' +Set.eq_of_nonempty_of_subsingleton' +Set.EqOn.piecewise_ite' +Set.eval_preimage' +Set.exists_intermediate_set' +Set.finite' +Set.finite_diff_iUnion_Ioo' +Set.Finite.eq_of_subset_of_encard_le' +Set.Finite.preimage' +Set.Finite.seq' +Set.Finite.toFinset_insert' +Set.fintypeBind' +Set.fintypeBiUnion' +Set.fintypeSeq' +Set.Icc_mul_Icc_subset' +Set.Icc_mul_Ico_subset' +Set.Icc_subset_uIcc' +Set.Icc_union_Icc' +Set.Icc_union_Ici' +Set.Ici_mul_Ici_subset' +Set.Ici_mul_Ioi_subset' +Set.Ico_mul_Icc_subset' +Set.Ico_mul_Ioc_subset' +Set.Ico_union_Ici' +Set.Ico_union_Ico' +Set.Iic_mul_Iic_subset' +Set.Iic_mul_Iio_subset' +Set.Iic_union_Icc' +Set.Iic_union_Ioc' +Set.iInter₂_mono' +Set.iInter_iInter_eq' +Set.iInter_mono' +Set.iInter_mono'' +Set.iInter_sigma' +Set.Iio_mul_Iic_subset' +Set.Iio_union_Ico' +Set.Iio_union_Ioo' +Set.image_affine_Icc' +Set.image_mul_left' +Set.image_mul_left_Icc' +Set.image_mul_right' +Set.image_mul_right_Icc' +Set.Infinite.preimage' +setIntegral_withDensity_eq_setIntegral_smul₀' +Set.Ioc_mul_Ico_subset' +Set.Ioc_subset_uIoc' +Set.Ioc_union_Ioc' +Set.Ioc_union_Ioi' +Set.Ioi_mul_Ici_subset' +Set.Ioo_union_Ioi' +Set.Ioo_union_Ioo' +Set.isScalarTower' +Set.isScalarTower'' +Set.iUnion₂_mono' +Set.iUnion_iUnion_eq' +Set.iUnion_mono' +Set.iUnion_mono'' +Set.iUnion_sigma' +Set.LeftInvOn.image_image' +Set.LeftInvOn.image_inter' +SetLike.ext' +Set.mapsTo' +Set.mapsTo_of_subsingleton' +Set.mulIndicator_apply_le' +Set.mulIndicator_compl' +Set.mulIndicator_diff' +Set.mulIndicator_div' +Set.mulIndicator_empty' +Set.mulIndicator_eq_one' +Set.mulIndicator_inv' +Set.mulIndicator_le' +Set.mulIndicator_le_mulIndicator' +Set.mulIndicator_le_self' +Set.mulIndicator_mul' +Set.mulIndicator_one' +Set.ncard_eq_toFinset_card' +Set.ncard_exchange' +Set.nonempty_of_ssubset' +Set.Nonempty.preimage' +Setoid.comm' +Setoid.eqv_class_mem' +Setoid.ext' +Setoid.ker_apply_mk_out' +Setoid.refl' +Setoid.symm' +Setoid.trans' +Set.ordConnected_iInter' +Set.OrdConnected.inter' +Set.ordConnected_pi' +Set.PairwiseDisjoint.elim' +Set.Pairwise.mono' +Set.piecewise_mem_Icc' +Set.pi_eq_empty_iff' +Set.PiSetCoe.canLift' +Set.preimage_eq_preimage' +Set.preimage_id' +Set.preimage_mul_left_one' +Set.preimage_mul_right_one' +Set.Quotient.range_mk'' +Set.range_id' +Set.range_ite_subset' +Set.range_quotient_lift_on' +Set.range_quotient_mk' +Set.setOf_eq_eq_singleton' +Set.singleton_pi' +Set.Sized.subsingleton' +Set.smulCommClass_set' +Set.smulCommClass_set'' +Set.smul_inter_ne_empty_iff' +Set.smul_univ₀' +Set.star_inv' +Set.star_mem_centralizer' +Set.surjOn_of_subsingleton' +SetTheory.Game.birthday_neg' +SetTheory.PGame.add_le_add_right' +SetTheory.PGame.Equiv.not_fuzzy' +SetTheory.PGame.Fuzzy.not_equiv' +SetTheory.PGame.LF.not_equiv' +SetTheory.PGame.moveLeft_neg' +SetTheory.PGame.moveLeft_neg_symm' +SetTheory.PGame.moveLeft_nim' +SetTheory.PGame.moveRight_neg' +SetTheory.PGame.moveRight_neg_symm' +SetTheory.PGame.moveRight_nim' +SetTheory.PGame.ofLists_moveLeft' +SetTheory.PGame.ofLists_moveRight' +SetTheory.PGame.relabel_moveLeft' +SetTheory.PGame.relabel_moveRight' +SetTheory.PGame.Subsequent.mk_right' +SetTheory.PGame.zero_lf_inv' +Set.uIcc_subset_uIcc_iff_le' +Set.union_diff_cancel' +Set.WellFoundedOn.mono' +Sigma.exists' +Sigma.forall' +sigma_mk_preimage_image' +SimpleGraph.Adj.ne' +SimpleGraph.cliqueSet_mono' +SimpleGraph.cycleGraph_adj' +SimpleGraph.dart_edge_eq_mk'_iff' +SimpleGraph.FarFromTriangleFree.cliqueFinset_nonempty' +SimpleGraph.Subgraph.connected_iff' +SimpleGraph.Subgraph.Connected.mono' +SimpleGraph.Subgraph.degree_le' +SimpleGraph.TripartiteFromTriangles.Graph.in₀₁_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₀₂_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₁₀_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₁₂_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₂₀_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₂₁_iff' +SimpleGraph.Walk.coe_support_append' +SimpleGraph.Walk.IsPath.mk' +simple_iff_isSimpleModule' +SimplexCategory.eq_comp_δ_of_not_surjective' +SimplexCategory.eq_σ_comp_of_not_injective' +SimplexCategory.Hom.ext' +SimplexCategory.δ_comp_δ' +SimplexCategory.δ_comp_δ'' +SimplexCategory.δ_comp_δ_self' +SimplexCategory.δ_comp_σ_of_gt' +SimplexCategory.δ_comp_σ_self' +SimplexCategory.δ_comp_σ_succ' +SimplicialObject.Splitting.hom_ext' +SimplicialObject.Splitting.IndexSet.ext' +sInf_eq_iInf' +sInf_image' +skewAdjoint.conjugate' +SlashInvariantForm.slash_action_eqn' +small_biInter' +small_iInter' +small_sInter' +smoothAt_finset_prod' +smooth_finset_prod' +SmoothManifoldWithCorners.mk' +SmoothMap.instSMul' +SmoothMap.module' +SmoothMap.smul_comp' +smoothOn_finset_prod' +SmoothPartitionOfUnity.sum_finsupport' +smoothWithinAt_finset_prod' +smul_ball'' +smul_closedBall' +smul_closedBall'' +SMulCommClass.nnrat' +SMulCommClass.rat' +smul_div' +smul_eq_smul_iff_eq_and_eq_of_pos' +smul_finprod' +smul_inv' +smul_left_injective' +smul_le_smul' +smul_lt_smul' +smul_lt_smul_of_le_of_lt' +smul_lt_smul_of_lt_of_le' +smul_mul' +smul_nonneg' +smul_pos' +smul_pow' +smul_sphere' +spec' +SpectralMap.coe_comp_continuousMap' +spinGroup.star_eq_inv' +sq_le_sq' +sq_lt_sq' +sSup_eq_bot' +sSup_eq_iSup' +sSup_image' +StarAlgHom.coe_mk' +star_comm_self' +StarConvex.sub' +star_inv' +Stream' +Stream'.drop_tail' +Stream'.get_succ_iterate' +Stream'.Seq1.map_join' +Stream'.tail_drop' +Stream'.take_succ' +StrictAnti.const_mul' +StrictAnti.ite' +StrictAnti.mul_const' +StrictAntiOn.const_mul' +StrictAntiOn.mul_const' +StrictMono.const_mul' +StrictMono.ite' +StrictMono.mul_const' +StrictMonoOn.const_mul' +StrictMonoOn.mul_const' +StrictWeakOrder.not_lt_of_equiv' +String.LT' +StructureGroupoid.LocalInvariantProp.congr' +StructureGroupoid.LocalInvariantProp.congr_nhdsWithin' +StructureGroupoid.LocalInvariantProp.liftPropWithinAt_inter' +Subalgebra.algebra' +Subalgebra.coe_valA' +Subalgebra.module' +Subbimodule.smul_mem' +sub_div' +Subgroup.center_eq_infi' +Subgroup.comap_equiv_eq_map_symm' +Subgroup.commutator_def' +Subgroup.disjoint_def' +Subgroup.eq_top_iff' +Subgroup.finiteIndex_iInf' +Subgroup.map_equiv_eq_comap_symm' +Subgroup.map_le_map_iff' +Subgroup.mem_normalizer_iff' +Subgroup.mem_normalizer_iff'' +Subgroup.mem_sup' +Subgroup.Normal.conj_mem' +Subgroup.quotient_finite_of_isOpen' +Subgroup.smul_diff' +Subgroup.smul_diff_smul' +Subgroup.smul_opposite_image_mul_preimage' +Subgroup.transferTransversal_apply' +Subgroup.transferTransversal_apply'' +Sublattice.coe_inf' +SubmoduleClass.module' +Submodule.coe_continuous_linearProjOfClosedCompl' +Submodule.coe_prodEquivOfIsCompl' +Submodule.coe_subtypeL' +Submodule.comap_smul' +Submodule.disjoint_def' +Submodule.disjoint_span_singleton' +Submodule.eq_top_iff' +Submodule.hasSMul' +Submodule.inhabited' +Submodule.isScalarTower' +Submodule.ker_liftQ_eq_bot' +Submodule.le_sInf' +Submodule.linearProjOfIsCompl_apply_right' +Submodule.map_smul' +Submodule.map_smul'' +Submodule.map_toAddSubmonoid' +Submodule.mem_annihilator' +Submodule.mem_colon' +Submodule.mem_ideal_smul_span_iff_exists_sum' +Submodule.mem_localized' +Submodule.mem_span_insert' +Submodule.mem_sup' +Submodule.module' +Submodule.orderIsoMapComap_apply' +Submodule.orderIsoMapComap_symm_apply' +Submodule.Quotient.distribMulAction' +Submodule.Quotient.distribSMul' +Submodule.Quotient.eq' +Submodule.Quotient.instSMul' +Submodule.Quotient.mk'_eq_mk' +Submodule.Quotient.module' +Submodule.Quotient.mulAction' +Submodule.Quotient.smulZeroClass' +Submodule.sInf_le' +Submodule.smul_mem_iff' +Submodule.smul_mem_span_smul' +Submodule.span_image' +Submodule.unique' +Submonoid.disjoint_def' +Submonoid.eq_top_iff' +Submonoid.LocalizationMap.eq' +Submonoid.LocalizationMap.map_mk' +Submonoid.LocalizationMap.mk'_eq_iff_eq' +Submonoid.LocalizationMap.mk'_eq_of_eq' +Submonoid.LocalizationMap.mk'_self' +Submonoid.LocalizationMap.mk'_spec' +Submonoid.LocalizationMap.mulEquivOfMulEquiv_mk' +Submonoid.LocalizationMap.mul_mk'_one_eq_mk' +Submonoid.LocalizationMap.sec_spec' +Submonoid.LocalizationMap.symm_comp_ofMulEquivOfLocalizations_apply' +Submonoid.mrange_inl' +Submonoid.mrange_inr' +SubMulAction.isScalarTower' +SubMulAction.mem_one' +SubMulAction.smul' +SubMulAction.smul_mem_iff' +Subring.closure_induction' +Subring.coe_mk' +Subring.eq_top_iff' +Subring.mem_mk' +Subsemigroup.eq_top_iff' +Subsemiring.closure_induction' +Subsemiring.coe_mk' +Subsemiring.eq_top_iff' +Subsemiring.mem_mk' +subset_interior_mul' +Subsingleton.antitone' +Subsingleton.monotone' +sub_sq' +Subtype.preimage_coe_compl' +SuccOrder.prelimitRecOn_succ' +suffixLevenshtein_nil' +sum_bernoulli' +summable_geometric_two' +Summable.matrix_blockDiag' +summable_matrix_blockDiagonal' +Summable.matrix_blockDiagonal' +summable_mul_of_summable_norm' +summable_of_isBigO' +summable_of_isBigO_nat' +summable_star_iff' +summable_sum_mul_antidiagonal_of_summable_norm' +summable_sum_mul_range_of_summable_norm' +sup_eq_half_smul_add_add_abs_sub' +sup_sdiff_cancel' +Surreal.dyadicMap_apply_pow' +Surreal.nsmul_pow_two_powHalf' +Sym2.instDecidableRel' +Sym2.mem_iff' +Sym2.other_eq_other' +Sym2.other_invol' +Sym2.other_mem' +Sym2.other_spec' +Sym2.rel_iff' +Sym.inhabitedSym' +symmDiff_eq' +symmDiff_eq_Xor' +symmDiff_symmDiff_right' +symmDiff_symmDiff_self' +symmDiff_top' +SymplecticGroup.coe_inv' +SymplecticGroup.mem_iff' +t0Space_iff_uniformity' +Tactic.NormNum.int_gcd_helper' +Tactic.NormNum.nat_gcd_helper_1' +Tactic.NormNum.nat_gcd_helper_2' +tendsto_ceil_left' +tendsto_ceil_right' +tendsto_const_mul_pow_nhds_iff' +tendsto_floor_left' +tendsto_floor_right' +tendsto_fract_left' +tendsto_fract_right' +tendsto_gauge_nhds_zero' +tendsto_indicator_const_apply_iff_eventually' +tendsto_indicator_const_iff_forall_eventually' +tendsto_indicator_const_iff_tendsto_pi_pure' +tendsto_measure_Icc_nhdsWithin_right' +tendsto_nhds_bot_mono' +tendsto_nhds_top_mono' +tendsto_nhds_unique' +tendsto_norm' +tendsto_norm_atTop_iff_cobounded' +tendsto_norm_cobounded_atTop' +tendsto_norm_cocompact_atTop' +tendsto_norm_zero' +TensorProduct.ext' +TensorProduct.finsuppLeft_smul' +TensorProduct.isPushout' +TensorProduct.lift.tmul' +TensorProduct.smul_tmul' +Theorems100.«82».Cube.hw' +Theorems100.num_series' +three_ne_zero' +toIcoDiv_add_left' +toIcoDiv_add_right' +toIcoDiv_add_zsmul' +toIcoDiv_neg' +toIcoDiv_sub' +toIcoDiv_sub_eq_toIcoDiv_add' +toIcoDiv_sub_zsmul' +toIcoMod_add_left' +toIcoMod_add_right' +toIcoMod_add_zsmul' +toIcoMod_mem_Ico' +toIcoMod_neg' +toIcoMod_sub' +toIcoMod_sub_zsmul' +toIcoMod_zsmul_add' +toIocDiv_add_left' +toIocDiv_add_right' +toIocDiv_add_zsmul' +toIocDiv_neg' +toIocDiv_sub' +toIocDiv_sub_eq_toIocDiv_add' +toIocDiv_sub_zsmul' +toIocMod_add_left' +toIocMod_add_right' +toIocMod_add_zsmul' +toIocMod_neg' +toIocMod_sub' +toIocMod_sub_zsmul' +toIocMod_zsmul_add' +toIxxMod_total' +TopCat.GlueData.preimage_image_eq_image' +TopCat.openEmbedding_iff_comp_isIso' +TopCat.openEmbedding_iff_isIso_comp' +TopCat.Presheaf.germ_stalkSpecializes' +TopCat.Presheaf.pushforward_eq' +TopCat.Presheaf.pushforward_map_app' +TopologicalGroup.of_nhds_one' +TopologicalSpace.OpenNhds.map_id_obj' +TopologicalSpace.Opens.coe_inclusion' +TopologicalSpace.Opens.map_comp_obj' +TopologicalSpace.Opens.map_functor_eq' +TopologicalSpace.Opens.map_id_obj' +TopologicalSpace.Opens.openEmbedding' +TopologicalSpace.Opens.set_range_forget_map_inclusion' +TopologicalSpace.SecondCountableTopology.mk' +Topology.WithScott.isOpen_iff_isUpperSet_and_scottHausdorff_open' +top_sdiff' +top_symmDiff' +toSubalgebra_toIntermediateField' +T_pow' +tprod_comm' +tprod_eq_prod' +tprod_eq_zero_mul' +tprod_le_of_prod_le' +tprod_prod' +tprod_sigma' +Traversable.map_traverse' +Traversable.naturality' +Traversable.traverse_eq_map_id' +Traversable.traverse_map' +Trivialization.apply_symm_apply' +Trivialization.coe_coordChangeL' +Trivialization.coe_fst' +Trivialization.coe_fst_eventuallyEq_proj' +Trivialization.continuousLinearEquivAt_apply' +Trivialization.ext' +Trivialization.mk_proj_snd' +Trivialization.proj_symm_apply' +TrivSqZeroExt.algebra' +TrivSqZeroExt.algebraMap_eq_inl' +TrivSqZeroExt.algHom_ext' +TrivSqZeroExt.snd_pow_of_smul_comm' +TruncatedWittVector.commutes' +TruncatedWittVector.commutes_symm' +tsum_choose_mul_geometric_of_norm_lt_one' +tsum_geometric_two' +tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm' +tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm' +tsum_mul_tsum_of_summable_norm' +Tuple.proj_equiv₁' +Turing.PartrecToTM2.trStmts₁_supports' +Turing.Reaches₀.tail' +Turing.Tape.exists_mk' +Turing.Tape.map_mk' +Turing.Tape.move_left_mk' +Turing.Tape.move_right_mk' +Turing.Tape.write_mk' +Turing.TM1to1.trTape_mk' +Turing.tr_eval' +two_ne_zero' +TwoSidedIdeal.mem_mk' +TypeVec.appendFun_comp' +TypeVec.drop_append1' +TypeVec.dropFun_RelLast' +TypeVec.subtypeVal_toSubtype' +TypeVec.toSubtype'_of_subtype' +ULift.distribMulAction' +ULift.distribSMul' +ULift.isometricSMul' +ULift.isScalarTower' +ULift.isScalarTower'' +ULift.module' +ULift.mulAction' +ULift.mulActionWithZero' +ULift.mulDistribMulAction' +ULift.smulWithZero' +ULift.smulZeroClass' +Ultrafilter.le_of_inf_neBot' +Ultrafilter.map_id' +UniformCauchySeqOn.prod' +uniformContinuous_comap' +UniformContinuous.const_mul' +uniformContinuous_div_const' +UniformContinuous.div_const' +UniformContinuous.mul_const' +uniformContinuous_mul_left' +uniformContinuous_mul_right' +uniformContinuous_nnnorm' +uniformContinuous_norm' +uniformEmbedding_iff' +UniformGroup.mk' +uniformInducing_iff' +UniformInducing.mk' +uniformity_basis_edist' +uniformity_basis_edist_le' +uniformity_eq_comap_nhds_one' +UniformSpace.Completion.ext' +unique' +uniqueDiffWithinAt_inter' +UniqueDiffWithinAt.inter' +UniqueFactorizationMonoid.exists_reduced_factors' +UniqueMDiffWithinAt.inter' +UniqueMDiffWithinAt.smooth_bundle_preimage' +Unique.subsingleton_unique' +Unique.subtypeEq' +unitary.star_eq_inv' +Unitization.algHom_ext'' +Unitization.quasispectrum_eq_spectrum_inr' +Units.coe_map' +Units.conj_pow' +Units.inv_mul' +Units.mul_inv' +UniversalEnvelopingAlgebra.lift_ι_apply' +update_le_update_iff' +upperClosure_interior_subset' +UpperHalfPlane.cosh_dist' +UpperHalfPlane.ext_iff' +UpperHalfPlane.ModularGroup.det_coe' +UpperHalfPlane.mul_smul' +UV.compress_of_disjoint_of_le' +Valuation.Integers.one_of_isUnit' +Valuation.map_add' +Valuation.map_sum_lt' +ValuationSubring.isIntegral_of_mem_ringOfIntegers' +Vector.continuous_insertNth' +VitaliFamily.ae_tendsto_lintegral_div' +volume_regionBetween_eq_integral' +volume_regionBetween_eq_lintegral' +WCovBy.of_le_of_le' +WeakBilin.instModule' +WeakSpace.instModule' +WeierstrassCurve.Affine.CoordinateRing.mk_XYIdeal'_mul_mk_XYIdeal' +WeierstrassCurve.Affine.equation_iff' +WeierstrassCurve.Affine.nonsingular_iff' +WeierstrassCurve.Affine.Point.add_of_X_ne' +WeierstrassCurve.Affine.Point.add_of_Y_ne' +WeierstrassCurve.Affine.Point.add_self_of_Y_ne' +WeierstrassCurve.baseChange_preΨ' +WeierstrassCurve.coeff_preΨ' +WeierstrassCurve.Jacobian.add_of_Y_ne' +WeierstrassCurve.Jacobian.addX_eq' +WeierstrassCurve.Jacobian.addX_of_X_eq' +WeierstrassCurve.Jacobian.addY_of_X_eq' +WeierstrassCurve.Jacobian.dblXYZ_of_Y_eq' +WeierstrassCurve.Jacobian.dblZ_ne_zero_of_Y_ne' +WeierstrassCurve.Jacobian.equiv_iff_eq_of_Z_eq' +WeierstrassCurve.Jacobian.isUnit_dblZ_of_Y_ne' +WeierstrassCurve.Jacobian.negAddY_eq' +WeierstrassCurve.Jacobian.negAddY_of_X_eq' +WeierstrassCurve.Jacobian.neg_of_Z_eq_zero' +WeierstrassCurve.Jacobian.Y_eq_iff' +WeierstrassCurve.Jacobian.Y_eq_of_Y_ne' +WeierstrassCurve.Jacobian.Y_ne_negY_of_Y_ne' +WeierstrassCurve.leadingCoeff_preΨ' +WeierstrassCurve.map_preΨ' +WeierstrassCurve.natDegree_coeff_preΨ' +WeierstrassCurve.natDegree_preΨ' +WeierstrassCurve.Projective.addX_eq' +WeierstrassCurve.Projective.addY_of_X_eq' +WeierstrassCurve.Projective.addZ_eq' +WeierstrassCurve.Projective.dblX_eq' +WeierstrassCurve.Projective.dblY_of_Y_eq' +WeierstrassCurve.Projective.dblZ_ne_zero_of_Y_ne' +WeierstrassCurve.Projective.equiv_iff_eq_of_Z_eq' +WeierstrassCurve.Projective.isUnit_dblZ_of_Y_ne' +WeierstrassCurve.Projective.negAddY_eq' +WeierstrassCurve.Projective.negAddY_of_X_eq' +WeierstrassCurve.Projective.negDblY_eq' +WeierstrassCurve.Projective.negDblY_of_Y_eq' +WeierstrassCurve.Projective.Y_eq_iff' +WeierstrassCurve.Projective.Y_eq_of_Y_ne' +WeierstrassCurve.Projective.Y_ne_negY_of_Y_ne' +WellFounded.monotone_chain_condition' +WfDvdMonoid.max_power_factor' +WithBot.bot_mul' +WithBot.coe_sInf' +WithBot.coe_sSup' +WithBot.le_coe_unbot' +WithBot.mul_bot' +WithBot.unbot_one' +WithTop.coe_sInf' +WithTop.coe_sSup' +WithTop.distrib' +WithTop.mul_top' +WithTop.top_mul' +WithTop.untop_one' +WithZero.map'_map' +WittVector.aeval_verschiebung_poly' +WittVector.exists_eq_pow_p_mul' +WittVector.idIsPolyI' +WittVector.nth_mul_coeff' +WittVector.poly_eq_of_wittPolynomial_bind_eq' +WittVector.RecursionBase.solution_spec' +WittVector.RecursionMain.succNthVal_spec' +WittVector.truncate_mk' +WriterT.callCC' +WriterT.goto_mkLabel' +WriterT.mkLabel' +WType.cardinal_mk_eq_sum' +WType.WType' +Xor' +xor_iff_not_iff' +X_pow_sub_C_eq_prod' +zero_le' +zero_lt_one_add_norm_sq' +zero_mem_ℓp' +zero_ne_one' +ZFSet.IsTransitive.sUnion' +ZMod.cast_add' +ZMod.cast_id' +ZMod.cast_intCast' +ZMod.cast_mul' +ZMod.cast_natCast' +ZMod.cast_one' +ZMod.cast_pow' +ZMod.cast_sub' +ZMod.intCast_eq_intCast_iff' +ZMod.invDFT_apply' +ZMod.invDFT_def' +ZMod.natCast_eq_natCast_iff' +ZMod.natCast_self' +ZMod.neg_val' +ZMod.nontrivial' +ZMod.val_mul' +ZMod.val_neg' +ZMod.val_one' +ZMod.val_one'' +ZMod.val_unit' +ZNum.cast_zero' +ZNum.of_to_int' +zpow_add' +zpow_eq_zpow_emod' +zpow_le_zpow' +zpow_le_zpow_iff' +zpow_lt_zpow' +zpow_lt_zpow_iff' +zpow_mul' +zsmul_eq_mul' +Zsqrtd.norm_eq_one_iff' diff --git a/test/DocPrime.lean b/test/DocPrime.lean new file mode 100644 index 0000000000000..3809fa9675e65 --- /dev/null +++ b/test/DocPrime.lean @@ -0,0 +1,80 @@ +import Mathlib.Tactic.Linter.DocPrime +import Mathlib.Tactic.Lemma + +set_option linter.docPrime true + +-- no warning on a primed-declaration with a doc-string containing `'` +/-- X' has a doc-string -/ +def X' := 0 + +-- no warning on a declaration whose name contains a `'` *and does not end with it* +def X'X := 0 + +-- A list of universe names in the declaration is handled correctly, i.e. warns. +/-- +warning: `Y'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +def Y'.{u} := ULift.{u} Nat + +namespace X +/-- +warning: `ABC.thm_no_doc1'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +theorem _root_.ABC.thm_no_doc1' : True := .intro + +/-- +warning: `X.thm_no_doc2'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +theorem thm_no_doc2' : True := .intro + +end X + +/-- +warning: `thm_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +theorem thm_no_doc' : True := .intro + +/-- +warning: `thm_with_attr_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +@[simp] +theorem thm_with_attr_no_doc' : True := .intro + +/-- +warning: `inst_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +instance inst_no_doc' : True := .intro + +/-- +warning: `abbrev_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +abbrev abbrev_no_doc' : True := .intro + +/-- +warning: `def_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +def def_no_doc' : True := .intro From be952f8338706af0b6b3bcc3ab6ee366cfcc0a25 Mon Sep 17 00:00:00 2001 From: D-Thomine <100795491+D-Thomine@users.noreply.github.com> Date: Wed, 25 Sep 2024 13:57:04 +0000 Subject: [PATCH 149/170] feat(Dynamics.TopologicalEntropy): add definition of topological entropy by nets (#16162) Third PR in a sequence to implement the notion of topological entropy for maps using Bowen-Dinaburg's formalism. This file introduces a definition of topological entropy using nets. - [x] Dynamical uniformities - [x] Topological entropy via covers - [x] Topological entropy via nets - [ ] Behaviour under semiconjugacy - [ ] Behaviour for subsets and unions - [ ] Behaviour under products - [ ] Full shift The main file is `Dynamics.TopologicalEntropy.NetEntropy`. It is slightly shorter and less technical than the previous one. There are also a few modifications to `Dynamics.TopologicalEntropy.CoverEntropy` (some golf, and renamed a lemma to enable dot notation -- which is quite convenient here). Paging @pitmonticone @sgouezel Co-authored-by: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com> --- Mathlib.lean | 1 + .../TopologicalEntropy/CoverEntropy.lean | 209 ++++----- .../TopologicalEntropy/NetEntropy.lean | 408 ++++++++++++++++++ 3 files changed, 515 insertions(+), 103 deletions(-) create mode 100644 Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean diff --git a/Mathlib.lean b/Mathlib.lean index 07a75add2567f..2f1502803917a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2642,6 +2642,7 @@ import Mathlib.Dynamics.OmegaLimit import Mathlib.Dynamics.PeriodicPts import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy import Mathlib.Dynamics.TopologicalEntropy.DynamicalEntourage +import Mathlib.Dynamics.TopologicalEntropy.NetEntropy import Mathlib.FieldTheory.AbelRuffini import Mathlib.FieldTheory.AbsoluteGaloisGroup import Mathlib.FieldTheory.Adjoin diff --git a/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean b/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean index 0333f199aa230..2b8f40fded2bf 100644 --- a/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean +++ b/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean @@ -19,7 +19,7 @@ A notable choice is that we define the topological entropy of a subset `F` of th Usually, one defines the entropy of an invariant subset `F` as the entropy of the restriction of the transformation to `F`. We avoid the latter definition as it would involve frequent manipulation of subtypes. Our version directly gives a meaning to the topological entropy of a subsystem, and a -single theorem (`subset_restriction_entropy` in `TopologicalEntropy.Morphism`) will give the +single theorem (`subset_restriction_entropy` in `TopologicalEntropy.Semiconj`) will give the equivalence between both versions. Another choice is to give a meaning to the entropy of `∅` (it must be `-∞` to stay coherent) and to @@ -28,11 +28,11 @@ reals `[-∞, +∞]`. The consequence is that we use `ℕ∞`, `ℝ≥0∞` and ## Main definitions - `IsDynCoverOf`: property that dynamical balls centered on a subset `s` cover a subset `F`. -- `coverMincard`: minimal cardinal of a dynamical cover. Takes values in `ℕ∞`. -- `coverEntropyInfEnt`/`coverEntropyEnt`: exponential growth of `coverMincard`. The former is -defined with a `liminf`, the later with a `limsup`. Take values in `EReal`. -- `coverEntropyInf`/`coverEntropy`: supremum of `coverEntropyInfEnt`/`coverEntropyEnt` over -all entourages (or limit as the entourages go to the diagonal). These are Bowen-Dinaburg's +- `coverMincard`: minimal cardinality of a dynamical cover. Takes values in `ℕ∞`. +- `coverEntropyInfEntourage`/`coverEntropyEntourage`: exponential growth of `coverMincard`. +The former is defined with a `liminf`, the later with a `limsup`. Take values in `EReal`. +- `coverEntropyInf`/`coverEntropy`: supremum of `coverEntropyInfEntourage`/`coverEntropyEntourage` +over all entourages (or limit as the entourages go to the diagonal). These are Bowen-Dinaburg's versions of the topological entropy with covers. Take values in `EReal`. ## Implementation notes @@ -46,8 +46,8 @@ using only `coverEntropy`. ## Main results - `IsDynCoverOf.iterate_le_pow`: given a dynamical cover at time `n`, creates dynamical covers at all iterates `n * m` with controlled cardinality. -- `IsDynCoverOf.coverEntropyEnt_le_log_card_div`: upper bound on `coverEntropyEnt` given any -dynamical cover. +- `IsDynCoverOf.coverEntropyEntourage_le_log_card_div`: upper bound on `coverEntropyEntourage` +given any dynamical cover. - `coverEntropyInf_eq_coverEntropy`: equality between the notions of topological entropy defined with a `liminf` and a `limsup`. @@ -56,11 +56,11 @@ cover, entropy ## TODO The most painful part of many manipulations involving topological entropy is going from -`coverMincard` to `coverEntropyInfEnt`/`coverEntropyEnt`. It involves a logarithm, a division, a -`liminf`/`limsup`, and multiple coercions. The best thing to do would be to write a file on -"exponential growth" to make a clean pathway from estimates on `coverMincard` to estimates on -`coverEntropyInf`/`coverEntropy`. It would also be useful in other similar contexts, including the -definition of entropy using nets. +`coverMincard` to `coverEntropyInfEntourage`/`coverEntropyEntourage`. It involves a logarithm, +a division, a `liminf`/`limsup`, and multiple coercions. The best thing to do would be to write +a file on "exponential growth" to make a clean pathway from estimates on `coverMincard` +to estimates on `coverEntropyInf`/`coverEntropy`. It would also be useful +in other similar contexts, including the definition of entropy using nets. Get versions of the topological entropy on (pseudo-e)metric spaces. -/ @@ -133,8 +133,8 @@ lemma IsDynCoverOf.nonempty_inter {T : X → X} {F : Set X} {U : Set (X × X)} { /-- From a dynamical cover `s` with entourage `U` and time `m`, we construct covers with entourage `U ○ U` and any multiple `m * n` of `m` with controlled cardinality. This lemma is the first step in a submultiplicative-like property of `coverMincard`, with consequences such as explicit bounds -for the topological entropy (`coverEntropyInfEnt_le_card_div`) and an equality between two notions -of topological entropy (`coverEntropyInf_eq_coverEntropySup_of_inv`).-/ +for the topological entropy (`coverEntropyInfEntourage_le_card_div`) and an equality between +two notions of topological entropy (`coverEntropyInf_eq_coverEntropySup_of_inv`).-/ lemma IsDynCoverOf.iterate_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {m : ℕ} (n : ℕ) {s : Finset X} (h : IsDynCoverOf T F U m s) : ∃ t : Finset X, IsDynCoverOf T F (U ○ U) (m * n) t ∧ t.card ≤ s.card ^ n := by @@ -234,8 +234,8 @@ lemma exists_isDynCoverOf_of_isCompact_invariant [UniformSpace X] {T : X → X} noncomputable def coverMincard (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : ℕ∞ := ⨅ (s : Finset X) (_ : IsDynCoverOf T F U n s), (s.card : ℕ∞) -lemma coverMincard_le_card {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} {s : Finset X} - (h : IsDynCoverOf T F U n s) : +lemma IsDynCoverOf.coverMincard_le_card {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} + {s : Finset X} (h : IsDynCoverOf T F U n s) : coverMincard T F U n ≤ s.card := iInf₂_le s h lemma coverMincard_monotone_time (T : X → X) (F : Set X) (U : Set (X × X)) : @@ -290,7 +290,7 @@ lemma coverMincard_zero (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X rcases h with ⟨x, _⟩ have := isDynCoverOf_zero T F U (singleton_nonempty x) rw [← Finset.coe_singleton] at this - apply le_of_le_of_eq (coverMincard_le_card this) + apply this.coverMincard_le_card.trans_eq rw [Finset.card_singleton, Nat.cast_one] lemma coverMincard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : @@ -299,7 +299,7 @@ lemma coverMincard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : rcases h with ⟨x, _⟩ have := isDynCoverOf_univ T F n (singleton_nonempty x) rw [← Finset.coe_singleton] at this - apply le_of_le_of_eq (coverMincard_le_card this) + apply this.coverMincard_le_card.trans_eq rw [Finset.card_singleton, Nat.cast_one] lemma coverMincard_mul_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} @@ -310,16 +310,16 @@ lemma coverMincard_mul_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) { rcases n.eq_zero_or_pos with rfl | n_pos · rw [mul_zero, coverMincard_zero T F_nonempty (U ○ U), pow_zero] rcases eq_top_or_lt_top (coverMincard T F U m) with h | h - · exact h ▸ le_of_le_of_eq (le_top (α := ℕ∞)) (ENat.top_pow n_pos).symm + · exact h ▸ (le_top (α := ℕ∞)).trans_eq (ENat.top_pow n_pos).symm · rcases (coverMincard_finite_iff T F U m).1 h with ⟨s, s_cover, s_coverMincard⟩ rcases s_cover.iterate_le_pow F_inv U_symm n with ⟨t, t_cover, t_le_sn⟩ rw [← s_coverMincard] - exact (coverMincard_le_card t_cover).trans (WithTop.coe_le_coe.2 t_le_sn) + exact t_cover.coverMincard_le_card.trans (WithTop.coe_le_coe.2 t_le_sn) lemma coverMincard_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {m : ℕ} (m_pos : 0 < m) (n : ℕ) : coverMincard T F (U ○ U) n ≤ coverMincard T F U m ^ (n / m + 1) := - (coverMincard_monotone_time T F (U ○ U) (le_of_lt (Nat.lt_mul_div_succ n m_pos))).trans + (coverMincard_monotone_time T F (U ○ U) (Nat.lt_mul_div_succ n m_pos).le).trans (coverMincard_mul_le_pow F_inv U_symm m (n / m + 1)) lemma coverMincard_finite_of_isCompact_uniformContinuous [UniformSpace X] {T : X → X} @@ -327,13 +327,13 @@ lemma coverMincard_finite_of_isCompact_uniformContinuous [UniformSpace X] {T : X (n : ℕ) : coverMincard T F U n < ⊤ := by rcases exists_isDynCoverOf_of_isCompact_uniformContinuous F_comp h U_uni n with ⟨s, s_cover⟩ - exact (coverMincard_le_card s_cover).trans_lt (WithTop.coe_lt_top s.card) + exact s_cover.coverMincard_le_card.trans_lt (WithTop.coe_lt_top s.card) lemma coverMincard_finite_of_isCompact_invariant [UniformSpace X] {T : X → X} {F : Set X} (F_comp : IsCompact F) (F_inv : MapsTo T F F) {U : Set (X × X)} (U_uni : U ∈ 𝓤 X) (n : ℕ) : coverMincard T F U n < ⊤ := by rcases exists_isDynCoverOf_of_isCompact_invariant F_comp F_inv U_uni n with ⟨s, s_cover⟩ - exact (coverMincard_le_card s_cover).trans_lt (WithTop.coe_lt_top s.card) + exact s_cover.coverMincard_le_card.trans_lt (WithTop.coe_lt_top s.card) /-- All dynamical balls of a minimal dynamical cover of `F` intersect `F`. This lemma is the key to relate Bowen-Dinaburg's definition of topological entropy with covers and their definition @@ -356,7 +356,7 @@ lemma nonempty_inter_of_coverMincard {T : X → X} {F : Set X} {U : Set (X × X) rw [← ball_empt] rw [z_x] at hz exact mem_inter y_F hz - apply not_lt_of_le (coverMincard_le_card smaller_cover) + apply smaller_cover.coverMincard_le_card.not_lt rw [← h'] exact_mod_cast Finset.card_erase_lt_of_mem x_s @@ -391,83 +391,82 @@ lemma log_coverMincard_le_add {T : X → X} {F : Set X} (F_inv : MapsTo T F F) have h_nm : (0 : EReal) ≤ (n / m : ℕ) := Nat.cast_nonneg' (n / m) have h_log := log_coverMincard_nonneg T F_nemp U m have n_div_n := EReal.div_self (natCast_ne_bot n) (natCast_ne_top n) - (ne_of_gt (Nat.cast_pos'.2 n_pos)) + (Nat.cast_pos'.2 n_pos).ne.symm apply le_trans <| div_le_div_right_of_nonneg (Nat.cast_pos'.2 n_pos).le (log_monotone (ENat.toENNReal_le.2 (coverMincard_le_pow F_inv U_symm m_pos n))) rw [ENat.toENNReal_pow, log_pow, Nat.cast_add, Nat.cast_one, right_distrib_of_nonneg h_nm zero_le_one, one_mul, div_right_distrib_of_nonneg (Left.mul_nonneg h_nm h_log) h_log, mul_comm, ← EReal.mul_div, div_eq_mul_inv _ (m : EReal)] apply add_le_add_right (mul_le_mul_of_nonneg_left _ h_log) - apply le_of_le_of_eq <| div_le_div_right_of_nonneg (Nat.cast_pos'.2 n_pos).le (natCast_div_le n m) + apply (div_le_div_right_of_nonneg (Nat.cast_pos'.2 n_pos).le (natCast_div_le n m)).trans_eq rw [EReal.div_div, mul_comm, ← EReal.div_div, n_div_n, one_div (m : EReal)] /-! ### Cover entropy of entourages -/ open Filter -/-- The entropy of an entourage `U` (`Ent` stands for "entourage"), defined as the exponential rate - of growth of the size of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of - extended real numbers `[-∞, +∞]`. This first version uses a `limsup`, and is chosen as the - default definition.-/ -noncomputable def coverEntropyEnt (T : X → X) (F : Set X) (U : Set (X × X)) := +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size + of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of extended real numbers + `[-∞, +∞]`. This first version uses a `limsup`, and is chosen as the default definition.-/ +noncomputable def coverEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := atTop.limsup fun n : ℕ ↦ log (coverMincard T F U n) / n -/-- The entropy of an entourage `U` (`Ent` stands for "entourage"), defined as the exponential rate - of growth of the size of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of - extended real numbers `[-∞, +∞]`. This second version uses a `liminf`, and is chosen as an - alternative definition.-/ -noncomputable def coverEntropyInfEnt (T : X → X) (F : Set X) (U : Set (X × X)) := +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size + of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of extended real numbers + `[-∞, +∞]`. This second version uses a `liminf`, and is chosen as an alternative definition.-/ +noncomputable def coverEntropyInfEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := atTop.liminf fun n : ℕ ↦ log (coverMincard T F U n) / n -lemma coverEntropyInfEnt_antitone (T : X → X) (F : Set X) : - Antitone (fun U : Set (X × X) ↦ coverEntropyInfEnt T F U) := +lemma coverEntropyInfEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ coverEntropyInfEntourage T F U) := fun _ _ U_V ↦ (liminf_le_liminf) <| Eventually.of_forall fun n ↦ monotone_div_right_of_nonneg (Nat.cast_nonneg' n) <| log_monotone (ENat.toENNReal_mono (coverMincard_antitone T F n U_V)) -lemma coverEntropyEnt_antitone (T : X → X) (F : Set X) : - Antitone (fun U : Set (X × X) ↦ coverEntropyEnt T F U) := +lemma coverEntropyEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ coverEntropyEntourage T F U) := fun _ _ U_V ↦ (limsup_le_limsup) <| Eventually.of_forall fun n ↦ monotone_div_right_of_nonneg (Nat.cast_nonneg' n) <| log_monotone (ENat.toENNReal_mono (coverMincard_antitone T F n U_V)) -lemma coverEntropyInfEnt_le_coverEntropyEnt (T : X → X) (F : Set X) (U : Set (X × X)) : - coverEntropyInfEnt T F U ≤ coverEntropyEnt T F U := liminf_le_limsup +lemma coverEntropyInfEntourage_le_coverEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) : + coverEntropyInfEntourage T F U ≤ coverEntropyEntourage T F U := liminf_le_limsup @[simp] -lemma coverEntropyEnt_empty {T : X → X} {U : Set (X × X)} : - coverEntropyEnt T ∅ U = ⊥ := by +lemma coverEntropyEntourage_empty {T : X → X} {U : Set (X × X)} : + coverEntropyEntourage T ∅ U = ⊥ := by suffices h : ∀ᶠ n : ℕ in atTop, log (coverMincard T ∅ U n) / n = ⊥ by - rw [coverEntropyEnt] + rw [coverEntropyEntourage] exact limsup_congr h ▸ limsup_const ⊥ · simp only [coverMincard_empty, ENat.toENNReal_zero, log_zero, eventually_atTop] exact ⟨1, fun n n_pos ↦ bot_div_of_pos_ne_top (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)⟩ @[simp] -lemma coverEntropyInfEnt_empty {T : X → X} {U : Set (X × X)} : - coverEntropyInfEnt T ∅ U = ⊥ := - eq_bot_mono (coverEntropyInfEnt_le_coverEntropyEnt T ∅ U) coverEntropyEnt_empty +lemma coverEntropyInfEntourage_empty {T : X → X} {U : Set (X × X)} : + coverEntropyInfEntourage T ∅ U = ⊥ := + eq_bot_mono (coverEntropyInfEntourage_le_coverEntropyEntourage T ∅ U) coverEntropyEntourage_empty -lemma coverEntropyInfEnt_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : - 0 ≤ coverEntropyInfEnt T F U := +lemma coverEntropyInfEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ coverEntropyInfEntourage T F U := (le_iInf fun n ↦ div_nonneg (log_coverMincard_nonneg T h U n) (Nat.cast_nonneg' n)).trans iInf_le_liminf -lemma coverEntropyEnt_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : - 0 ≤ coverEntropyEnt T F U := - (coverEntropyInfEnt_nonneg T h U).trans (coverEntropyInfEnt_le_coverEntropyEnt T F U) +lemma coverEntropyEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ coverEntropyEntourage T F U := + (coverEntropyInfEntourage_nonneg T h U).trans + (coverEntropyInfEntourage_le_coverEntropyEntourage T F U) -lemma coverEntropyEnt_univ (T : X → X) {F : Set X} (h : F.Nonempty) : - coverEntropyEnt T F univ = 0 := by - simp [coverEntropyEnt, coverMincard_univ T h] +lemma coverEntropyEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + coverEntropyEntourage T F univ = 0 := by + simp [coverEntropyEntourage, coverMincard_univ T h] -lemma coverEntropyInfEnt_univ (T : X → X) {F : Set X} (h : F.Nonempty) : - coverEntropyInfEnt T F univ = 0 := by - simp [coverEntropyInfEnt, coverMincard_univ T h] +lemma coverEntropyInfEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + coverEntropyInfEntourage T F univ = 0 := by + simp [coverEntropyInfEntourage, coverMincard_univ T h] -lemma coverEntropyEnt_le_log_coverMincard_div {T : X → X} {F : Set X} (F_inv : MapsTo T F F) +lemma coverEntropyEntourage_le_log_coverMincard_div {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {n : ℕ} (n_pos : 0 < n) : - coverEntropyEnt T F (U ○ U) ≤ log (coverMincard T F U n) / n := by + coverEntropyEntourage T F (U ○ U) ≤ log (coverMincard T F U n) / n := by -- Deal with the edge cases: `F = ∅` or `F` has no finite cover. rcases eq_or_ne (log (coverMincard T F U n)) ⊥ with logm_bot | logm_nneg · rw [log_eq_bot_iff, ← ENat.toENNReal_zero, ENat.toENNReal_coe_eq_iff, @@ -487,46 +486,48 @@ lemma coverEntropyEnt_le_log_coverMincard_div {T : X → X} {F : Set X} (F_inv : have := @limsup_add_le_add_limsup ℕ atTop u v rw [h, add_zero] at this specialize this (Or.inr EReal.zero_ne_top) (Or.inr EReal.zero_ne_bot) - exact le_of_le_of_eq this (limsup_const (log (coverMincard T F U n) / n)) + exact this.trans_eq (limsup_const (log (coverMincard T F U n) / n)) exact Tendsto.limsup_eq (EReal.tendsto_const_div_atTop_nhds_zero_nat logm_nneg logm_fin) -lemma IsDynCoverOf.coverEntropyEnt_le_log_card_div {T : X → X} {F : Set X} (F_inv : MapsTo T F F) - {U : Set (X × X)} (U_symm : SymmetricRel U) {n : ℕ} (n_pos : 0 < n) {s : Finset X} - (h : IsDynCoverOf T F U n s) : - coverEntropyEnt T F (U ○ U) ≤ log s.card / n := by - apply (coverEntropyEnt_le_log_coverMincard_div F_inv U_symm n_pos).trans +lemma IsDynCoverOf.coverEntropyEntourage_le_log_card_div {T : X → X} {F : Set X} + (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {n : ℕ} (n_pos : 0 < n) + {s : Finset X} (h : IsDynCoverOf T F U n s) : + coverEntropyEntourage T F (U ○ U) ≤ log s.card / n := by + apply (coverEntropyEntourage_le_log_coverMincard_div F_inv U_symm n_pos).trans apply monotone_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) exact_mod_cast coverMincard_le_card h -lemma coverEntropyEnt_le_coverEntropyInfEnt {T : X → X} {F : Set X} (F_inv : MapsTo T F F) - {U : Set (X × X)} (U_symm : SymmetricRel U) : - coverEntropyEnt T F (U ○ U) ≤ coverEntropyInfEnt T F U := +lemma coverEntropyEntourage_le_coverEntropyInfEntourage {T : X → X} {F : Set X} + (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) : + coverEntropyEntourage T F (U ○ U) ≤ coverEntropyInfEntourage T F U := (le_liminf_of_le) (eventually_atTop.2 - ⟨1, fun m m_pos ↦ coverEntropyEnt_le_log_coverMincard_div F_inv U_symm m_pos⟩) + ⟨1, fun m m_pos ↦ coverEntropyEntourage_le_log_coverMincard_div F_inv U_symm m_pos⟩) -lemma coverEntropyEnt_finite_of_isCompact_invariant [UniformSpace X] {T : X → X} {F : Set X} +lemma coverEntropyEntourage_finite_of_isCompact_invariant [UniformSpace X] {T : X → X} {F : Set X} (F_comp : IsCompact F) (F_inv : MapsTo T F F) {U : Set (X × X)} (U_uni : U ∈ 𝓤 X) : - coverEntropyEnt T F U < ⊤ := by + coverEntropyEntourage T F U < ⊤ := by rcases comp_symm_mem_uniformity_sets U_uni with ⟨V, V_uni, V_symm, V_U⟩ rcases exists_isDynCoverOf_of_isCompact_invariant F_comp F_inv V_uni 1 with ⟨s, s_cover⟩ - apply (coverEntropyEnt_antitone T F V_U).trans_lt - apply (s_cover.coverEntropyEnt_le_log_card_div F_inv V_symm zero_lt_one).trans_lt + apply (coverEntropyEntourage_antitone T F V_U).trans_lt + apply (s_cover.coverEntropyEntourage_le_log_card_div F_inv V_symm zero_lt_one).trans_lt rw [Nat.cast_one, div_one, log_lt_top_iff, ← ENat.toENNReal_top] exact_mod_cast Ne.lt_top (ENat.coe_ne_top (Finset.card s)) /-! ### Cover entropy -/ -/-- The entropy of `T` restricted to `F`, obtained by taking the supremum over entourages. - Note that this supremum is approached by taking small entourages. This first version uses a - `limsup`, and is chosen as the default definition for topological entropy.-/ +/-- The entropy of `T` restricted to `F`, obtained by taking the supremum + of `coverEntropyEntourage` over entourages. Note that this supremum is approached by taking small + entourages. This first version uses a `limsup`, and is chosen as the default definition + for topological entropy.-/ noncomputable def coverEntropy [UniformSpace X] (T : X → X) (F : Set X) := - ⨆ U ∈ 𝓤 X, coverEntropyEnt T F U + ⨆ U ∈ 𝓤 X, coverEntropyEntourage T F U -/-- The entropy of `T` restricted to `F`, obtained by taking the supremum over entourages. - Note that this supremum is approached by taking small entourages. This second version uses a - `liminf`, and is chosen as an alternative definition for topological entropy.-/ +/-- The entropy of `T` restricted to `F`, obtained by taking the supremum + of `coverEntropyInfEntourage` over entourages. Note that this supremum is approached by taking + small entourages. This second version uses a `liminf`, and is chosen as an alternative + definition for topological entropy.-/ noncomputable def coverEntropyInf [UniformSpace X] (T : X → X) (F : Set X) := - ⨆ U ∈ 𝓤 X, coverEntropyInfEnt T F U + ⨆ U ∈ 𝓤 X, coverEntropyInfEntourage T F U lemma coverEntropyInf_antitone (T : X → X) (F : Set X) : Antitone fun (u : UniformSpace X) ↦ @coverEntropyInf X u T F := @@ -538,49 +539,51 @@ lemma coverEntropy_antitone (T : X → X) (F : Set X) : variable [UniformSpace X] -lemma coverEntropyEnt_le_coverEntropy (T : X → X) (F : Set X) {U : Set (X × X)} (h : U ∈ 𝓤 X) : - coverEntropyEnt T F U ≤ coverEntropy T F := - le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyEnt T F U) U h +lemma coverEntropyEntourage_le_coverEntropy (T : X → X) (F : Set X) {U : Set (X × X)} + (h : U ∈ 𝓤 X) : + coverEntropyEntourage T F U ≤ coverEntropy T F := + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyEntourage T F U) U h -lemma coverEntropyInfEnt_le_coverEntropyInf (T : X → X) (F : Set X) {U : Set (X × X)} +lemma coverEntropyInfEntourage_le_coverEntropyInf (T : X → X) (F : Set X) {U : Set (X × X)} (h : U ∈ 𝓤 X) : - coverEntropyInfEnt T F U ≤ coverEntropyInf T F := - le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyInfEnt T F U) U h + coverEntropyInfEntourage T F U ≤ coverEntropyInf T F := + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyInfEntourage T F U) U h lemma coverEntropy_eq_iSup_basis {ι : Sort*} {p : ι → Prop} {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : - coverEntropy T F = ⨆ (i : ι) (_ : p i), coverEntropyEnt T F (s i) := by + coverEntropy T F = ⨆ (i : ι) (_ : p i), coverEntropyEntourage T F (s i) := by refine (iSup₂_le fun U U_uni ↦ ?_).antisymm (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩) rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ - exact (coverEntropyEnt_antitone T F si_U).trans - (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyEnt T F (s i)) i h_i) + exact (coverEntropyEntourage_antitone T F si_U).trans + (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyEntourage T F (s i)) i h_i) lemma coverEntropyInf_eq_iSup_basis {ι : Sort*} {p : ι → Prop} {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : - coverEntropyInf T F = ⨆ (i : ι) (_ : p i), coverEntropyInfEnt T F (s i) := by + coverEntropyInf T F = ⨆ (i : ι) (_ : p i), coverEntropyInfEntourage T F (s i) := by refine (iSup₂_le fun U U_uni ↦ ?_).antisymm (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩) rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ - exact (coverEntropyInfEnt_antitone T F si_U).trans - (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyInfEnt T F (s i)) i h_i) + exact (coverEntropyInfEntourage_antitone T F si_U).trans + (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyInfEntourage T F (s i)) i h_i) lemma coverEntropyInf_le_coverEntropy (T : X → X) (F : Set X) : coverEntropyInf T F ≤ coverEntropy T F := - iSup₂_mono fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyInfEnt_le_coverEntropyEnt T F U + iSup₂_mono fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ + coverEntropyInfEntourage_le_coverEntropyEntourage T F U @[simp] lemma coverEntropy_empty {T : X → X} : coverEntropy T ∅ = ⊥ := by - simp only [coverEntropy, coverEntropyEnt_empty, iSup_bot] + simp only [coverEntropy, coverEntropyEntourage_empty, iSup_bot] @[simp] lemma coverEntropyInf_empty {T : X → X} : coverEntropyInf T ∅ = ⊥ := by - simp only [coverEntropyInf, coverEntropyInfEnt_empty, iSup_bot] + simp only [coverEntropyInf, coverEntropyInfEntourage_empty, iSup_bot] lemma coverEntropyInf_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) : 0 ≤ coverEntropyInf T F := - le_of_eq_of_le (coverEntropyInfEnt_univ T h).symm - (coverEntropyInfEnt_le_coverEntropyInf T F univ_mem) + (coverEntropyInfEntourage_le_coverEntropyInf T F univ_mem).trans_eq' + (coverEntropyInfEntourage_univ T h).symm lemma coverEntropy_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) : 0 ≤ coverEntropy T F := @@ -590,7 +593,7 @@ lemma coverEntropyInf_eq_coverEntropy (T : X → X) {F : Set X} (h : MapsTo T F coverEntropyInf T F = coverEntropy T F := by refine le_antisymm (coverEntropyInf_le_coverEntropy T F) (iSup₂_le fun U U_uni ↦ ?_) rcases comp_symm_mem_uniformity_sets U_uni with ⟨V, V_uni, V_symm, V_U⟩ - exact (coverEntropyEnt_antitone T F V_U).trans - (le_iSup₂_of_le V V_uni (coverEntropyEnt_le_coverEntropyInfEnt h V_symm)) + exact (coverEntropyEntourage_antitone T F V_U).trans + (le_iSup₂_of_le V V_uni (coverEntropyEntourage_le_coverEntropyInfEntourage h V_symm)) end Dynamics diff --git a/Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean b/Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean new file mode 100644 index 0000000000000..7720c694f1ce9 --- /dev/null +++ b/Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean @@ -0,0 +1,408 @@ +/- +Copyright (c) 2024 Damien Thomine. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damien Thomine, Pietro Monticone +-/ +import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy + +/-! +# Topological entropy via nets +We implement Bowen-Dinaburg's definitions of the topological entropy, via nets. + +The major design decisions are the same as in `Mathlib.Dynamics.TopologicalEntropy.CoverEntropy`, +and are explained in detail there: use of uniform spaces, definition of the topological entropy of +a subset, and values taken in `EReal`. + +Given a map `T : X → X` and a subset `F ⊆ X`, the topological entropy is loosely defined using +nets as the exponential growth (in `n`) of the number of distinguishable orbits of length `n` +starting from `F`. More precisely, given an entourage `U`, two orbits of length `n` can be +distinguished if there exists some index `k < n` such that `T^[k] x` and `T^[k] y` are far enough +(i.e. `(T^[k] x, T^[k] y)` is not in `U`). The maximal number of distinguishable orbits of +length `n` is `netMaxcard T F U n`, and its exponential growth `netEntropyEntourage T F U`. This +quantity increases when `U` decreases, and a definition of the topological entropy is +`⨆ U ∈ 𝓤 X, netEntropyInfEntourage T F U`. + +The definition of topological entropy using nets coincides with the definition using covers. +Instead of defining a new notion of topological entropy, we prove that +`coverEntropy` coincides with `⨆ U ∈ 𝓤 X, netEntropyEntourage T F U`. + +## Main definitions +- `IsDynNetIn`: property that dynamical balls centered on a subset `s` of `F` are disjoint. +- `netMaxcard`: maximal cardinality of a dynamical net. Takes values in `ℕ∞`. +- `netEntropyInfEntourage`/`netEntropyEntourage`: exponential growth of `netMaxcard`. The former is +defined with a `liminf`, the latter with a `limsup`. Take values in `EReal`. + +## Implementation notes +As when using covers, there are two competing definitions `netEntropyInfEntourage` and +`netEntropyEntourage` in this file: one uses a `liminf`, the other a `limsup`. When using covers, +we chose the `limsup` definition as the default. + +## Main results +- `coverEntropy_eq_iSup_netEntropyEntourage`: equality between the notions of topological entropy +defined with covers and with nets. Has a variant for `coverEntropyInf`. + +## Tags +net, entropy + +## TODO +Get versions of the topological entropy on (pseudo-e)metric spaces. +-/ + +namespace Dynamics + +open Set Uniformity UniformSpace + +variable {X : Type*} + +/-! ### Dynamical nets -/ + +/-- Given a subset `F`, an entourage `U` and an integer `n`, a subset `s` of `F` is a +`(U, n)`-dynamical net of `F` if no two orbits of length `n` of points in `s` shadow each other.-/ +def IsDynNetIn (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) (s : Set X) : Prop := + s ⊆ F ∧ s.PairwiseDisjoint (fun x : X ↦ ball x (dynEntourage T U n)) + +lemma IsDynNetIn.of_le {T : X → X} {F : Set X} {U : Set (X × X)} {m n : ℕ} (m_n : m ≤ n) {s : Set X} + (h : IsDynNetIn T F U m s) : + IsDynNetIn T F U n s := + ⟨h.1, PairwiseDisjoint.mono h.2 (fun x ↦ ball_mono (dynEntourage_antitone T U m_n) x)⟩ + +lemma IsDynNetIn.of_entourage_subset {T : X → X} {F : Set X} {U V : Set (X × X)} (U_V : U ⊆ V) + {n : ℕ} {s : Set X} (h : IsDynNetIn T F V n s) : + IsDynNetIn T F U n s := + ⟨h.1, PairwiseDisjoint.mono h.2 (fun x ↦ ball_mono (dynEntourage_monotone T n U_V) x)⟩ + +lemma isDynNetIn_empty {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} : + IsDynNetIn T F U n ∅ := + ⟨empty_subset F, pairwise_empty _⟩ + +lemma isDynNetIn_singleton (T : X → X) {F : Set X} (U : Set (X × X)) (n : ℕ) {x : X} (h : x ∈ F) : + IsDynNetIn T F U n {x} := + ⟨singleton_subset_iff.2 h, pairwise_singleton x _⟩ + +/-- Given an entourage `U` and a time `n`, a dynamical net has a smaller cardinality than + a dynamical cover. This lemma is the first of two key results to compare two versions of + topological entropy: with cover and with nets, the second being `coverMincard_le_netMaxcard`.-/ +lemma IsDynNetIn.card_le_card_of_isDynCoverOf {T : X → X} {F : Set X} {U : Set (X × X)} + (U_symm : SymmetricRel U) {n : ℕ} {s t : Finset X} (hs : IsDynNetIn T F U n s) + (ht : IsDynCoverOf T F U n t) : + s.card ≤ t.card := by + have (x : X) (x_s : x ∈ s) : ∃ z ∈ t, x ∈ ball z (dynEntourage T U n) := by + specialize ht (hs.1 x_s) + simp only [Finset.coe_sort_coe, mem_iUnion, Subtype.exists, exists_prop] at ht + exact ht + choose! F s_t using this + simp only [mem_ball_symmetry (U_symm.dynEntourage T n)] at s_t + apply Finset.card_le_card_of_injOn F (fun x x_s ↦ (s_t x x_s).1) + exact fun x x_s y y_s Fx_Fy ↦ + PairwiseDisjoint.elim_set hs.2 x_s y_s (F x) (s_t x x_s).2 (Fx_Fy ▸ (s_t y y_s).2) + +/-! ### Maximal cardinality of dynamical nets -/ + +/-- The largest cardinality of a `(U, n)`-dynamical net of `F`. Takes values in `ℕ∞`, and is +infinite if and only if `F` admits nets of arbitrarily large size.-/ +noncomputable def netMaxcard (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : ℕ∞ := + ⨆ (s : Finset X) (_ : IsDynNetIn T F U n s), (s.card : ℕ∞) + +lemma IsDynNetIn.card_le_netMaxcard {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} {s : Finset X} + (h : IsDynNetIn T F U n s) : + s.card ≤ netMaxcard T F U n := + le_iSup₂ (α := ℕ∞) s h + +lemma netMaxcard_monotone_time (T : X → X) (F : Set X) (U : Set (X × X)) : + Monotone (fun n : ℕ ↦ netMaxcard T F U n) := + fun _ _ m_n ↦ biSup_mono (fun _ h ↦ h.of_le m_n) + +lemma netMaxcard_antitone (T : X → X) (F : Set X) (n : ℕ) : + Antitone (fun U : Set (X × X) ↦ netMaxcard T F U n) := + fun _ _ U_V ↦ biSup_mono (fun _ h ↦ h.of_entourage_subset U_V) + +lemma netMaxcard_finite_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + netMaxcard T F U n < ⊤ ↔ + ∃ s : Finset X, IsDynNetIn T F U n s ∧ (s.card : ℕ∞) = netMaxcard T F U n := by + apply Iff.intro <;> intro h + · rcases WithTop.ne_top_iff_exists.1 h.ne with ⟨k, k_max⟩ + rw [← k_max] + simp only [ENat.some_eq_coe, Nat.cast_inj] + -- The criterion we want to use is `Nat.sSup_mem`. We rewrite `netMaxcard` with an `sSup`, + -- then check its `BddAbove` and `Nonempty` hypotheses. + have : netMaxcard T F U n + = sSup (WithTop.some '' (Finset.card '' {s : Finset X | IsDynNetIn T F U n s})) := by + rw [netMaxcard, ← image_comp, sSup_image] + simp only [mem_setOf_eq, ENat.some_eq_coe, Function.comp_apply] + rw [this] at k_max + have h_bdda : BddAbove (Finset.card '' {s : Finset X | IsDynNetIn T F U n s}) := by + refine ⟨k, mem_upperBounds.2 ?_⟩ + simp only [mem_image, mem_setOf_eq, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + intro s h + rw [← WithTop.coe_le_coe, k_max] + apply le_sSup + simp only [ENat.some_eq_coe, mem_image, mem_setOf_eq, Nat.cast_inj, exists_eq_right] + exact Filter.frequently_principal.mp fun a ↦ a h rfl + have h_nemp : (Finset.card '' {s : Finset X | IsDynNetIn T F U n s}).Nonempty := by + refine ⟨0, ?_⟩ + simp only [mem_image, mem_setOf_eq, Finset.card_eq_zero, exists_eq_right, Finset.coe_empty] + exact isDynNetIn_empty + rw [← WithTop.coe_sSup' h_bdda, ENat.some_eq_coe, Nat.cast_inj] at k_max + have key := Nat.sSup_mem h_nemp h_bdda + rw [← k_max, mem_image] at key + simp only [mem_setOf_eq] at key + exact key + · rcases h with ⟨s, _, s_netMaxcard⟩ + rw [← s_netMaxcard] + exact WithTop.coe_lt_top s.card + +@[simp] +lemma netMaxcard_empty {T : X → X} {U : Set (X × X)} {n : ℕ} : netMaxcard T ∅ U n = 0 := by + rw [netMaxcard, ← bot_eq_zero, iSup₂_eq_bot] + intro s s_net + replace s_net := subset_empty_iff.1 s_net.1 + norm_cast at s_net + rw [s_net, Finset.card_empty, CharP.cast_eq_zero, bot_eq_zero'] + +lemma netMaxcard_eq_zero_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + netMaxcard T F U n = 0 ↔ F = ∅ := by + refine Iff.intro (fun h ↦ ?_) (fun h ↦ by rw [h, netMaxcard_empty]) + rw [eq_empty_iff_forall_not_mem] + intro x x_F + have key := isDynNetIn_singleton T U n x_F + rw [← Finset.coe_singleton] at key + replace key := key.card_le_netMaxcard + rw [Finset.card_singleton, Nat.cast_one, h] at key + exact key.not_lt zero_lt_one + +lemma one_le_netMaxcard_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + 1 ≤ netMaxcard T F U n ↔ F.Nonempty := by + rw [ENat.one_le_iff_ne_zero, nonempty_iff_ne_empty] + exact not_iff_not.2 (netMaxcard_eq_zero_iff T F U n) + +lemma netMaxcard_zero (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + netMaxcard T F U 0 = 1 := by + apply (iSup₂_le _).antisymm ((one_le_netMaxcard_iff T F U 0).2 h) + intro s ⟨_, s_net⟩ + simp only [ball, dynEntourage_zero, preimage_univ] at s_net + norm_cast + refine Finset.card_le_one.2 (fun x x_s y y_s ↦ ?_) + exact PairwiseDisjoint.elim_set s_net x_s y_s x (mem_univ x) (mem_univ x) + +lemma netMaxcard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : + netMaxcard T F univ n = 1 := by + apply (iSup₂_le _).antisymm ((one_le_netMaxcard_iff T F univ n).2 h) + intro s ⟨_, s_net⟩ + simp only [ball, dynEntourage_univ, preimage_univ] at s_net + norm_cast + refine Finset.card_le_one.2 (fun x x_s y y_s ↦ ?_) + exact PairwiseDisjoint.elim_set s_net x_s y_s x (mem_univ x) (mem_univ x) + +lemma netMaxcard_infinite_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + netMaxcard T F U n = ⊤ ↔ ∀ k : ℕ, ∃ s : Finset X, IsDynNetIn T F U n s ∧ k ≤ s.card := by + apply Iff.intro <;> intro h + · intro k + rw [netMaxcard, iSup_subtype', iSup_eq_top] at h + specialize h k (ENat.coe_lt_top k) + simp only [Nat.cast_lt, Subtype.exists, exists_prop] at h + rcases h with ⟨s, s_net, s_k⟩ + exact ⟨s, ⟨s_net, s_k.le⟩⟩ + · refine WithTop.forall_gt_iff_eq_top.1 fun k ↦ ?_ + specialize h (k + 1) + rcases h with ⟨s, s_net, s_card⟩ + apply s_net.card_le_netMaxcard.trans_lt' + rw [ENat.some_eq_coe, Nat.cast_lt] + exact (lt_add_one k).trans_le s_card + +lemma netMaxcard_le_coverMincard (T : X → X) (F : Set X) {U : Set (X × X)} (U_symm : SymmetricRel U) + (n : ℕ) : + netMaxcard T F U n ≤ coverMincard T F U n := by + rcases eq_top_or_lt_top (coverMincard T F U n) with h | h + · exact h ▸ le_top + · rcases ((coverMincard_finite_iff T F U n).1 h) with ⟨t, t_cover, t_mincard⟩ + rw [← t_mincard] + exact iSup₂_le (fun s s_net ↦ Nat.cast_le.2 (s_net.card_le_card_of_isDynCoverOf U_symm t_cover)) + +/-- Given an entourage `U` and a time `n`, a minimal dynamical cover by `U ○ U` has a smaller + cardinality than a maximal dynamical net by `U`. This lemma is the second of two key results to + compare two versions topological entropy: with cover and with nets.-/ +lemma coverMincard_le_netMaxcard (T : X → X) (F : Set X) {U : Set (X × X)} (U_rfl : idRel ⊆ U) + (U_symm : SymmetricRel U) (n : ℕ) : + coverMincard T F (U ○ U) n ≤ netMaxcard T F U n := by + classical + -- WLOG, there exists a maximal dynamical net `s`. + rcases (eq_top_or_lt_top (netMaxcard T F U n)) with h | h + · exact h ▸ le_top + rcases ((netMaxcard_finite_iff T F U n).1 h) with ⟨s, s_net, s_netMaxcard⟩ + rw [← s_netMaxcard] + apply IsDynCoverOf.coverMincard_le_card + -- We have to check that `s` is a cover for `dynEntourage T F (U ○ U) n`. + -- If `s` is not a cover, then we can add to `s` a point `x` which is not covered + -- and get a new net. This contradicts the maximality of `s`. + by_contra h + rcases not_subset.1 h with ⟨x, x_F, x_uncov⟩ + simp only [Finset.mem_coe, mem_iUnion, exists_prop, not_exists, not_and] at x_uncov + have larger_net : IsDynNetIn T F U n (insert x s) := + And.intro (insert_subset x_F s_net.1) (pairwiseDisjoint_insert.2 (And.intro s_net.2 + (fun y y_s _ ↦ (disjoint_left.2 (fun z z_x z_y ↦ x_uncov y y_s + (mem_ball_dynEntourage_comp T n U_symm x y (nonempty_of_mem ⟨z_x, z_y⟩))))))) + rw [← Finset.coe_insert x s] at larger_net + apply larger_net.card_le_netMaxcard.not_lt + rw [← s_netMaxcard, Nat.cast_lt] + refine (lt_add_one s.card).trans_eq (Finset.card_insert_of_not_mem fun x_s ↦ ?_).symm + apply x_uncov x x_s (ball_mono (dynEntourage_monotone T n (subset_comp_self U_rfl)) x + (ball_mono (idRel_subset_dynEntourage T U_rfl n) x _)) + simp only [ball, mem_preimage, mem_idRel] + +open ENNReal EReal + +lemma log_netMaxcard_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) (n : ℕ) : + 0 ≤ log (netMaxcard T F U n) := by + apply zero_le_log_iff.2 + rw [← ENat.toENNReal_one, ENat.toENNReal_le] + exact (one_le_netMaxcard_iff T F U n).2 h + +/-! ### Net entropy of entourages -/ + +open Filter + +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size of the +largest `(U, n)`-dynamical net of `F`. Takes values in the space of extended real numbers +`[-∞,+∞]`. This version uses a `limsup`, and is chosen as the default definition.-/ +noncomputable def netEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := + atTop.limsup fun n : ℕ ↦ log (netMaxcard T F U n) / n + +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size of the +largest `(U, n)`-dynamical net of `F`. Takes values in the space of extended real numbers +`[-∞,+∞]`. This version uses a `liminf`, and is an alternative definition.-/ +noncomputable def netEntropyInfEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := + atTop.liminf fun n : ℕ ↦ log (netMaxcard T F U n) / n + +lemma netEntropyInfEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ netEntropyInfEntourage T F U) := + fun _ _ U_V ↦ (liminf_le_liminf) (Eventually.of_forall + fun n ↦ monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (netMaxcard_antitone T F n U_V)))) + +lemma netEntropyEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ netEntropyEntourage T F U) := + fun _ _ U_V ↦ (limsup_le_limsup) (Eventually.of_forall + fun n ↦ (monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (netMaxcard_antitone T F n U_V))))) + +lemma netEntropyInfEntourage_le_netEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) : + netEntropyInfEntourage T F U ≤ netEntropyEntourage T F U := liminf_le_limsup + +@[simp] +lemma netEntropyEntourage_empty {T : X → X} {U : Set (X × X)} : netEntropyEntourage T ∅ U = ⊥ := by + suffices h : ∀ᶠ n : ℕ in atTop, log (netMaxcard T ∅ U n) / n = ⊥ by + rw [netEntropyEntourage, limsup_congr h] + exact limsup_const ⊥ + simp only [netMaxcard_empty, ENat.toENNReal_zero, log_zero, eventually_atTop] + exact ⟨1, fun n n_pos ↦ bot_div_of_pos_ne_top (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)⟩ + +@[simp] +lemma netEntropyInfEntourage_empty {T : X → X} {U : Set (X × X)} : + netEntropyInfEntourage T ∅ U = ⊥ := + eq_bot_mono (netEntropyInfEntourage_le_netEntropyEntourage T ∅ U) netEntropyEntourage_empty + +lemma netEntropyInfEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ netEntropyInfEntourage T F U := + (le_iInf fun n ↦ div_nonneg (log_netMaxcard_nonneg T h U n) (Nat.cast_nonneg' n)).trans + iInf_le_liminf + +lemma netEntropyEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ netEntropyEntourage T F U := + (netEntropyInfEntourage_nonneg T h U).trans (netEntropyInfEntourage_le_netEntropyEntourage T F U) + +lemma netEntropyInfEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + netEntropyInfEntourage T F univ = 0 := by simp [netEntropyInfEntourage, netMaxcard_univ T h] + +lemma netEntropyEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + netEntropyEntourage T F univ = 0 := by simp [netEntropyEntourage, netMaxcard_univ T h] + +lemma netEntropyInfEntourage_le_coverEntropyInfEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_symm : SymmetricRel U) : + netEntropyInfEntourage T F U ≤ coverEntropyInfEntourage T F U := + (liminf_le_liminf) (Eventually.of_forall fun n ↦ (div_le_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_le.2 (netMaxcard_le_coverMincard T F U_symm n))))) + +lemma coverEntropyInfEntourage_le_netEntropyInfEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_rfl : idRel ⊆ U) (U_symm : SymmetricRel U) : + coverEntropyInfEntourage T F (U ○ U) ≤ netEntropyInfEntourage T F U := by + refine (liminf_le_liminf) (Eventually.of_forall fun n ↦ ?_) + apply div_le_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) + exact ENat.toENNReal_le.2 (coverMincard_le_netMaxcard T F U_rfl U_symm n) + +lemma netEntropyEntourage_le_coverEntropyEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_symm : SymmetricRel U) : + netEntropyEntourage T F U ≤ coverEntropyEntourage T F U := by + refine (limsup_le_limsup) (Eventually.of_forall fun n ↦ ?_) + apply div_le_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) + exact ENat.toENNReal_le.2 (netMaxcard_le_coverMincard T F U_symm n) + +lemma coverEntropyEntourage_le_netEntropyEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_rfl : idRel ⊆ U) (U_symm : SymmetricRel U) : + coverEntropyEntourage T F (U ○ U) ≤ netEntropyEntourage T F U := by + refine (limsup_le_limsup) (Eventually.of_forall fun n ↦ ?_) + apply div_le_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) + exact ENat.toENNReal_le.2 (coverMincard_le_netMaxcard T F U_rfl U_symm n) + +/-! ### Relationship with entropy via covers -/ + +variable [UniformSpace X] (T : X → X) (F : Set X) + +/-- Bowen-Dinaburg's definition of topological entropy using nets is + `⨆ U ∈ 𝓤 X, netEntropyEntourage T F U`. This quantity is the same as the topological entropy using + covers, so there is no need to define a new notion of topological entropy. This version of the + theorem relates the `liminf` versions of topological entropy.-/ +theorem coverEntropyInf_eq_iSup_netEntropyInfEntourage : + coverEntropyInf T F = ⨆ U ∈ 𝓤 X, netEntropyInfEntourage T F U := by + apply le_antisymm <;> refine iSup₂_le fun U U_uni ↦ ?_ + · rcases (comp_symm_mem_uniformity_sets U_uni) with ⟨V, V_uni, V_symm, V_comp_U⟩ + apply (coverEntropyInfEntourage_antitone T F V_comp_U).trans (le_iSup₂_of_le V V_uni _) + exact coverEntropyInfEntourage_le_netEntropyInfEntourage T F (refl_le_uniformity V_uni) V_symm + · apply (netEntropyInfEntourage_antitone T F (symmetrizeRel_subset_self U)).trans + apply (le_iSup₂ (symmetrizeRel U) (symmetrize_mem_uniformity U_uni)).trans' + exact netEntropyInfEntourage_le_coverEntropyInfEntourage T F (symmetric_symmetrizeRel U) + +/-- Bowen-Dinaburg's definition of topological entropy using nets is + `⨆ U ∈ 𝓤 X, netEntropyEntourage T F U`. This quantity is the same as the topological entropy using + covers, so there is no need to define a new notion of topological entropy. This version of the + theorem relates the `limsup` versions of topological entropy.-/ +theorem coverEntropy_eq_iSup_netEntropyEntourage : + coverEntropy T F = ⨆ U ∈ 𝓤 X, netEntropyEntourage T F U := by + apply le_antisymm <;> refine iSup₂_le fun U U_uni ↦ ?_ + · rcases (comp_symm_mem_uniformity_sets U_uni) with ⟨V, V_uni, V_symm, V_comp_U⟩ + apply (coverEntropyEntourage_antitone T F V_comp_U).trans (le_iSup₂_of_le V V_uni _) + exact coverEntropyEntourage_le_netEntropyEntourage T F (refl_le_uniformity V_uni) V_symm + · apply (netEntropyEntourage_antitone T F (symmetrizeRel_subset_self U)).trans + apply (le_iSup₂ (symmetrizeRel U) (symmetrize_mem_uniformity U_uni)).trans' + exact netEntropyEntourage_le_coverEntropyEntourage T F (symmetric_symmetrizeRel U) + +lemma coverEntropyInf_eq_iSup_basis_netEntropyInfEntourage {ι : Sort*} {p : ι → Prop} + {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : + coverEntropyInf T F = ⨆ (i : ι) (_ : p i), netEntropyInfEntourage T F (s i) := by + rw [coverEntropyInf_eq_iSup_netEntropyInfEntourage T F] + apply (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩).antisymm' + refine iSup₂_le fun U U_uni ↦ ?_ + rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ + apply (netEntropyInfEntourage_antitone T F si_U).trans + exact le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ netEntropyInfEntourage T F (s i)) i h_i + +lemma coverEntropy_eq_iSup_basis_netEntropyEntourage {ι : Sort*} {p : ι → Prop} + {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : + coverEntropy T F = ⨆ (i : ι) (_ : p i), netEntropyEntourage T F (s i) := by + rw [coverEntropy_eq_iSup_netEntropyEntourage T F] + apply (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩).antisymm' + refine iSup₂_le fun U U_uni ↦ ?_ + rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ + apply (netEntropyEntourage_antitone T F si_U).trans _ + exact le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ netEntropyEntourage T F (s i)) i h_i + +lemma netEntropyInfEntourage_le_coverEntropyInf {U : Set (X × X)} (h : U ∈ 𝓤 X) : + netEntropyInfEntourage T F U ≤ coverEntropyInf T F := + coverEntropyInf_eq_iSup_netEntropyInfEntourage T F ▸ + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ netEntropyInfEntourage T F U) U h + +lemma netEntropyEntourage_le_coverEntropy {U : Set (X × X)} (h : U ∈ 𝓤 X) : + netEntropyEntourage T F U ≤ coverEntropy T F := + coverEntropy_eq_iSup_netEntropyEntourage T F ▸ + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ netEntropyEntourage T F U) U h + +end Dynamics From a95aae112143332f4f21618ff217e17b50be5dc7 Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Wed, 25 Sep 2024 14:12:15 +0000 Subject: [PATCH 150/170] feat(CategoryTheory/Limits): dualize Pi.isoLimit to Sigma.isoColimit (#17076) --- .../Limits/Shapes/Products.lean | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean index e0595886fe9d9..aa816cb1ee4da 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean @@ -481,6 +481,50 @@ from a family of isomorphisms between the factors. abbrev Sigma.mapIso {f g : β → C} [HasCoproductsOfShape β C] (p : ∀ b, f b ≅ g b) : ∐ f ≅ ∐ g := colim.mapIso (Discrete.natIso fun X => p X.as) +section + +/- In this section, we provide some API for coproducts when we are given a functor +`Discrete α ⥤ C` instead of a map `α → C`. -/ + +variable (X : Discrete α ⥤ C) [HasCoproduct (fun j => X.obj (Discrete.mk j))] + +/-- A colimit cocone for `X : Discrete α ⥤ C` that is given +by `∐ (fun j => X.obj (Discrete.mk j))`. -/ +@[simps] +def Sigma.cocone : Cocone X where + pt := ∐ (fun j => X.obj (Discrete.mk j)) + ι := Discrete.natTrans (fun _ => Sigma.ι (fun j ↦ X.obj ⟨j⟩) _) + +/-- The cocone `Sigma.cocone X` is a colimit cocone. -/ +def coproductIsCoproduct' : + IsColimit (Sigma.cocone X) where + desc s := Sigma.desc (fun j => s.ι.app ⟨j⟩) + fac s := by simp + uniq s m hm := by + dsimp + ext + simp only [colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app] + apply hm + +variable [HasColimit X] + +/-- The isomorphism `∐ (fun j => X.obj (Discrete.mk j)) ≅ colimit X`. -/ +def Sigma.isoColimit : + ∐ (fun j => X.obj (Discrete.mk j)) ≅ colimit X := + IsColimit.coconePointUniqueUpToIso (coproductIsCoproduct' X) (colimit.isColimit X) + +@[reassoc (attr := simp)] +lemma Sigma.ι_isoColimit_hom (j : α) : + Sigma.ι _ j ≫ (Sigma.isoColimit X).hom = colimit.ι _ (Discrete.mk j) := + IsColimit.comp_coconePointUniqueUpToIso_hom (coproductIsCoproduct' X) _ _ + +@[reassoc (attr := simp)] +lemma Sigma.ι_isoColimit_inv (j : α) : + colimit.ι _ ⟨j⟩ ≫ (Sigma.isoColimit X).inv = Sigma.ι (fun j ↦ X.obj ⟨j⟩) _ := + IsColimit.comp_coconePointUniqueUpToIso_inv _ _ _ + +end + /-- Two products which differ by an equivalence in the indexing type, and up to isomorphism in the factors, are isomorphic. -/ From 5f551d9f89a062d62820d2b02d2f7782fc5dbf98 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 25 Sep 2024 15:52:12 +0000 Subject: [PATCH 151/170] chore(Set/Image): rename 2 lemmas (#17134) Use `existsUnique`, not `exists_unique` in 2 lemmas --- Mathlib/Data/Fintype/Basic.lean | 2 +- Mathlib/Data/Set/Image.lean | 12 ++++++++---- .../CanonicalEmbedding/FundamentalCone.lean | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index e18eca0fb06df..1852e40e4fd39 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -492,7 +492,7 @@ This function computes by checking all terms `a : α` to find the `f a = b`, so -/ def invOfMemRange : Set.range f → α := fun b => Finset.choose (fun a => f a = b) Finset.univ - ((existsUnique_congr (by simp)).mp (hf.exists_unique_of_mem_range b.property)) + ((existsUnique_congr (by simp)).mp (hf.existsUnique_of_mem_range b.property)) theorem left_inv_of_invOfMemRange (b : Set.range f) : f (hf.invOfMemRange b) = b := (Finset.choose_spec (fun a => f a = b) _ _).right diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index a7b8fb2b64c6d..9d317af2926e5 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -1100,13 +1100,17 @@ theorem Surjective.range_comp {ι' : Sort*} {f : ι → ι'} (hf : Surjective f) range (g ∘ f) = range g := ext fun y => (@Surjective.exists _ _ _ hf fun x => g x = y).symm -theorem Injective.mem_range_iff_exists_unique (hf : Injective f) {b : β} : +theorem Injective.mem_range_iff_existsUnique (hf : Injective f) {b : β} : b ∈ range f ↔ ∃! a, f a = b := ⟨fun ⟨a, h⟩ => ⟨a, h, fun _ ha => hf (ha.trans h.symm)⟩, ExistsUnique.exists⟩ -theorem Injective.exists_unique_of_mem_range (hf : Injective f) {b : β} (hb : b ∈ range f) : - ∃! a, f a = b := - hf.mem_range_iff_exists_unique.mp hb +alias ⟨Injective.existsUnique_of_mem_range, _⟩ := Injective.mem_range_iff_existsUnique + +@[deprecated (since := "2024-09-25")] +alias Injective.mem_range_iff_exists_unique := Injective.mem_range_iff_existsUnique + +@[deprecated (since := "2024-09-25")] +alias Injective.exists_unique_of_mem_range := Injective.existsUnique_of_mem_range theorem Injective.compl_image_eq (hf : Injective f) (s : Set α) : (f '' s)ᶜ = f '' sᶜ ∪ (range f)ᶜ := by diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean index 911bb6fc07048..f9b153340e1c4 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean @@ -262,7 +262,7 @@ that `mixedEmbedding K x = a`. -/ theorem exists_unique_preimage_of_integralPoint {a : mixedSpace K} (ha : a ∈ integralPoint K) : ∃! x : (𝓞 K), mixedEmbedding K x = a := by obtain ⟨_, ⟨x, rfl⟩⟩ := mem_integralPoint.mp ha - refine Function.Injective.exists_unique_of_mem_range ?_ (Set.mem_range_self x) + refine Function.Injective.existsUnique_of_mem_range ?_ (Set.mem_range_self x) exact (mixedEmbedding_injective K).comp RingOfIntegers.coe_injective theorem integralPoint_ne_zero (a : integralPoint K) : (a : mixedSpace K) ≠ 0 := by From 15dec28087d004fe2b06c085b54c795c7c3b3c54 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Wed, 25 Sep 2024 19:13:54 +0000 Subject: [PATCH 152/170] =?UTF-8?q?feat:=20`M=E1=B4=B4=20*=20M=20=3D=201`?= =?UTF-8?q?=20when=20`M=20:=3D=20a.toBasis.toMatrix=20b`=20(#17136)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This partially generalizes an existing result to work when the indices are different. --- Mathlib/Analysis/InnerProductSpace/PiL2.lean | 27 ++++++++++++++++--- Mathlib/Data/Matrix/ColumnRowPartitioned.lean | 13 ++------- .../Matrix/NonsingularInverse.lean | 14 ++++++++++ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/Mathlib/Analysis/InnerProductSpace/PiL2.lean b/Mathlib/Analysis/InnerProductSpace/PiL2.lean index 12ea8605df263..8bf622dbce6f5 100644 --- a/Mathlib/Analysis/InnerProductSpace/PiL2.lean +++ b/Mathlib/Analysis/InnerProductSpace/PiL2.lean @@ -679,6 +679,28 @@ section ToMatrix variable [DecidableEq ι] section +open scoped Matrix + +/-- A version of `OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary` that works for bases with +different index types. -/ +@[simp] +theorem OrthonormalBasis.toMatrix_orthonormalBasis_conjTranspose_mul_self [Fintype ι'] + (a : OrthonormalBasis ι' 𝕜 E) (b : OrthonormalBasis ι 𝕜 E) : + (a.toBasis.toMatrix b)ᴴ * a.toBasis.toMatrix b = 1 := by + ext i j + convert a.repr.inner_map_map (b i) (b j) + rw [orthonormal_iff_ite.mp b.orthonormal i j] + rfl + +/-- A version of `OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary` that works for bases with +different index types. -/ +@[simp] +theorem OrthonormalBasis.toMatrix_orthonormalBasis_self_mul_conjTranspose [Fintype ι'] + (a : OrthonormalBasis ι 𝕜 E) (b : OrthonormalBasis ι' 𝕜 E) : + a.toBasis.toMatrix b * (a.toBasis.toMatrix b)ᴴ = 1 := by + classical + rw [Matrix.mul_eq_one_comm_of_equiv (a.toBasis.indexEquiv b.toBasis), + a.toMatrix_orthonormalBasis_conjTranspose_mul_self b] variable (a b : OrthonormalBasis ι 𝕜 E) @@ -686,10 +708,7 @@ variable (a b : OrthonormalBasis ι 𝕜 E) theorem OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary : a.toBasis.toMatrix b ∈ Matrix.unitaryGroup ι 𝕜 := by rw [Matrix.mem_unitaryGroup_iff'] - ext i j - convert a.repr.inner_map_map (b i) (b j) - rw [orthonormal_iff_ite.mp b.orthonormal i j] - rfl + exact a.toMatrix_orthonormalBasis_conjTranspose_mul_self b /-- The determinant of the change-of-basis matrix between two orthonormal bases `a`, `b` has unit length. -/ diff --git a/Mathlib/Data/Matrix/ColumnRowPartitioned.lean b/Mathlib/Data/Matrix/ColumnRowPartitioned.lean index 6961195e3a83e..1fef44043ba64 100644 --- a/Mathlib/Data/Matrix/ColumnRowPartitioned.lean +++ b/Mathlib/Data/Matrix/ColumnRowPartitioned.lean @@ -258,17 +258,8 @@ lemma fromColumns_mul_fromRows_eq_one_comm [Fintype n₁] [Fintype n₂] [Fintype n] [DecidableEq n] [DecidableEq n₁] [DecidableEq n₂] (e : n ≃ n₁ ⊕ n₂) (A₁ : Matrix n n₁ R) (A₂ : Matrix n n₂ R) (B₁ : Matrix n₁ n R) (B₂ : Matrix n₂ n R) : - fromColumns A₁ A₂ * fromRows B₁ B₂ = 1 ↔ fromRows B₁ B₂ * fromColumns A₁ A₂ = 1 := by - calc fromColumns A₁ A₂ * fromRows B₁ B₂ = 1 - _ ↔ submatrix (fromColumns A₁ A₂) id e * submatrix (fromRows B₁ B₂) e id = 1 := by - simp - _ ↔ submatrix (fromRows B₁ B₂) e id * submatrix (fromColumns A₁ A₂) id e = 1 := - mul_eq_one_comm - _ ↔ reindex e.symm e.symm (fromRows B₁ B₂ * fromColumns A₁ A₂) = reindex e.symm e.symm 1 := by - simp only [reindex_apply, Equiv.symm_symm, submatrix_one_equiv, - submatrix_mul (he₂ := Function.bijective_id)] - _ ↔ fromRows B₁ B₂ * fromColumns A₁ A₂ = 1 := - (reindex _ _).injective.eq_iff + fromColumns A₁ A₂ * fromRows B₁ B₂ = 1 ↔ fromRows B₁ B₂ * fromColumns A₁ A₂ = 1 := + mul_eq_one_comm_of_equiv e /-- The lemma `fromColumns_mul_fromRows_eq_one_comm` specialized to the case where the index sets n₁ and n₂, are the result of subtyping by a predicate and its complement. -/ diff --git a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean index e91010d1bc343..0ba84d9e908d0 100644 --- a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean +++ b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean @@ -175,6 +175,20 @@ theorem det_ne_zero_of_right_inverse [Nontrivial α] (h : A * B = 1) : A.det ≠ end Invertible + +section + +variable [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing α] + +/-- A version of `mul_eq_one_comm` that works for square matrices with rectangular types. -/ +theorem mul_eq_one_comm_of_equiv {A : Matrix m n α} {B : Matrix n m α} (e : m ≃ n) : + A * B = 1 ↔ B * A = 1 := by + refine (reindex e e).injective.eq_iff.symm.trans ?_ + rw [reindex_apply, reindex_apply, submatrix_one_equiv, ← submatrix_mul_equiv _ _ _ (.refl _), + mul_eq_one_comm, submatrix_mul_equiv, coe_refl, submatrix_id_id] + +end + section Inv variable [Fintype n] [DecidableEq n] [CommRing α] From 691fdda97493a0425b7b775a9c0112468890ddf6 Mon Sep 17 00:00:00 2001 From: Yoh Tanimoto <57562556+yoh-tanimoto@users.noreply.github.com> Date: Wed, 25 Sep 2024 20:50:00 +0000 Subject: [PATCH 153/170] chore(Analysis/InnerProductSpace): weaken assumptions to `SeminormedAddCommGroup` (#17007) replace the assumption `NormedAddCommGroup` to `SemiNormedAddCommGroup` in various places. motivation: with the weakened assumption the results apply to `InnerProductSpace` without `definite` assumption. This is suggested in #16707, and continues from #14024. Co-authored-by: Eric Wieser --- Mathlib/Analysis/InnerProductSpace/Basic.lean | 196 +++++++++--------- .../Analysis/InnerProductSpace/Symmetric.lean | 70 ++++--- .../Analysis/Normed/Module/Completion.lean | 2 +- 3 files changed, 140 insertions(+), 128 deletions(-) diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index aff60c1cd6250..07b4bdc761b64 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -1003,27 +1003,12 @@ theorem coe_basisOfOrthonormalOfCardEqFinrank [Fintype ι] [Nonempty ι] {v : ι (basisOfOrthonormalOfCardEqFinrank hv card_eq : ι → E) = v := coe_basisOfLinearIndependentOfCardEqFinrank _ _ -end OrthonormalSets_Seminormed - -section OrthonormalSets - -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] -variable [NormedAddCommGroup F] [InnerProductSpace ℝ F] -variable {ι : Type*} - -local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y - -local notation "IK" => @RCLike.I 𝕜 _ - -local postfix:90 "†" => starRingEnd _ - theorem Orthonormal.ne_zero {v : ι → E} (hv : Orthonormal 𝕜 v) (i : ι) : v i ≠ 0 := by - have : ‖v i‖ ≠ 0 := by - rw [hv.1 i] - norm_num - simpa using this + refine ne_of_apply_ne norm ?_ + rw [hv.1 i, norm_zero] + norm_num -end OrthonormalSets +end OrthonormalSets_Seminormed section Norm_Seminormed @@ -1198,9 +1183,9 @@ instance (priority := 100) InnerProductSpace.toUniformConvexSpace : UniformConve ring_nf exact sub_le_sub_left (pow_le_pow_left hε.le hxy _) 4⟩ -section Complex +section Complex_Seminormed -variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] +variable {V : Type*} [SeminormedAddCommGroup V] [InnerProductSpace ℂ V] /-- A complex polarization identity, with a linear map -/ @@ -1226,6 +1211,12 @@ theorem inner_map_polarization' (T : V →ₗ[ℂ] V) (x y : V) : mul_add, ← mul_assoc, mul_neg, neg_neg, sub_neg_eq_add, one_mul, neg_one_mul, mul_sub, sub_sub] ring +end Complex_Seminormed + +section Complex + +variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] + /-- A linear map `T` is zero, if and only if the identity `⟪T x, x⟫_ℂ = 0` holds for all `x`. -/ theorem inner_map_self_eq_zero (T : V →ₗ[ℂ] V) : (∀ x : V, ⟪T x, x⟫_ℂ = 0) ↔ T = 0 := by @@ -1551,7 +1542,7 @@ variable {𝕜} namespace ContinuousLinearMap -variable {E' : Type*} [NormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] +variable {E' : Type*} [SeminormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] -- Note: odd and expensive build behavior is explicitly turned off using `noncomputable` /-- Given `f : E →L[𝕜] E'`, construct the continuous sesquilinear form `fun x y ↦ ⟪x, A y⟫`, given @@ -1576,6 +1567,83 @@ theorem toSesqForm_apply_norm_le {f : E →L[𝕜] E'} {v : E'} : ‖toSesqForm end ContinuousLinearMap +section + +variable {ι : Type*} {ι' : Type*} {ι'' : Type*} +variable {E' : Type*} [SeminormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] +variable {E'' : Type*} [SeminormedAddCommGroup E''] [InnerProductSpace 𝕜 E''] + +@[simp] +theorem Orthonormal.equiv_refl {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) : + hv.equiv hv (Equiv.refl ι) = LinearIsometryEquiv.refl 𝕜 E := + v.ext_linearIsometryEquiv fun i => by + simp only [Orthonormal.equiv_apply, Equiv.coe_refl, id, LinearIsometryEquiv.coe_refl] + +@[simp] +theorem Orthonormal.equiv_symm {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) {v' : Basis ι' 𝕜 E'} + (hv' : Orthonormal 𝕜 v') (e : ι ≃ ι') : (hv.equiv hv' e).symm = hv'.equiv hv e.symm := + v'.ext_linearIsometryEquiv fun i => + (hv.equiv hv' e).injective <| by + simp only [LinearIsometryEquiv.apply_symm_apply, Orthonormal.equiv_apply, e.apply_symm_apply] + +end + +variable (𝕜) + +/-- `innerSL` is an isometry. Note that the associated `LinearIsometry` is defined in +`InnerProductSpace.Dual` as `toDualMap`. -/ +@[simp] +theorem innerSL_apply_norm (x : E) : ‖innerSL 𝕜 x‖ = ‖x‖ := by + refine + le_antisymm ((innerSL 𝕜 x).opNorm_le_bound (norm_nonneg _) fun y => norm_inner_le_norm _ _) ?_ + rcases (norm_nonneg x).eq_or_gt with (h | h) + · simp [h] + · refine (mul_le_mul_right h).mp ?_ + calc + ‖x‖ * ‖x‖ = ‖(⟪x, x⟫ : 𝕜)‖ := by + rw [← sq, inner_self_eq_norm_sq_to_K, norm_pow, norm_ofReal, abs_norm] + _ ≤ ‖innerSL 𝕜 x‖ * ‖x‖ := (innerSL 𝕜 x).le_opNorm _ + +lemma norm_innerSL_le : ‖innerSL 𝕜 (E := E)‖ ≤ 1 := + ContinuousLinearMap.opNorm_le_bound _ zero_le_one (by simp) + +variable {𝕜} + +/-- When an inner product space `E` over `𝕜` is considered as a real normed space, its inner +product satisfies `IsBoundedBilinearMap`. + +In order to state these results, we need a `NormedSpace ℝ E` instance. We will later establish +such an instance by restriction-of-scalars, `InnerProductSpace.rclikeToReal 𝕜 E`, but this +instance may be not definitionally equal to some other “natural” instance. So, we assume +`[NormedSpace ℝ E]`. +-/ +theorem _root_.isBoundedBilinearMap_inner [NormedSpace ℝ E] [IsScalarTower ℝ 𝕜 E] : + IsBoundedBilinearMap ℝ fun p : E × E => ⟪p.1, p.2⟫ := + { add_left := inner_add_left + smul_left := fun r x y => by + simp only [← algebraMap_smul 𝕜 r x, algebraMap_eq_ofReal, inner_smul_real_left] + add_right := inner_add_right + smul_right := fun r x y => by + simp only [← algebraMap_smul 𝕜 r y, algebraMap_eq_ofReal, inner_smul_real_right] + bound := + ⟨1, zero_lt_one, fun x y => by + rw [one_mul] + exact norm_inner_le_norm x y⟩ } + +/-- The inner product of two weighted sums, where the weights in each +sum add to 0, in terms of the norms of pairwise differences. -/ +theorem inner_sum_smul_sum_smul_of_sum_eq_zero {ι₁ : Type*} {s₁ : Finset ι₁} {w₁ : ι₁ → ℝ} + (v₁ : ι₁ → F) (h₁ : ∑ i ∈ s₁, w₁ i = 0) {ι₂ : Type*} {s₂ : Finset ι₂} {w₂ : ι₂ → ℝ} + (v₂ : ι₂ → F) (h₂ : ∑ i ∈ s₂, w₂ i = 0) : + ⟪∑ i₁ ∈ s₁, w₁ i₁ • v₁ i₁, ∑ i₂ ∈ s₂, w₂ i₂ • v₂ i₂⟫_ℝ = + (-∑ i₁ ∈ s₁, ∑ i₂ ∈ s₂, w₁ i₁ * w₂ i₂ * (‖v₁ i₁ - v₂ i₂‖ * ‖v₁ i₁ - v₂ i₂‖)) / 2 := by + simp_rw [sum_inner, inner_sum, real_inner_smul_left, real_inner_smul_right, + real_inner_eq_norm_mul_self_add_norm_mul_self_sub_norm_sub_mul_self_div_two, ← div_sub_div_same, + ← div_add_div_same, mul_sub_left_distrib, left_distrib, Finset.sum_sub_distrib, + Finset.sum_add_distrib, ← Finset.mul_sum, ← Finset.sum_mul, h₁, h₂, zero_mul, + mul_zero, Finset.sum_const_zero, zero_add, zero_sub, Finset.mul_sum, neg_div, + Finset.sum_div, mul_div_assoc, mul_assoc] + end Norm_Seminormed section Norm @@ -1611,27 +1679,6 @@ theorem dist_div_norm_sq_smul {x y : F} (hx : x ≠ 0) (hy : y ≠ 0) (R : ℝ) _ = R ^ 2 / (‖x‖ * ‖y‖) * dist x y := by rw [sqrt_mul, sqrt_sq, sqrt_sq, dist_eq_norm] <;> positivity -section - -variable {ι : Type*} {ι' : Type*} {ι'' : Type*} -variable {E' : Type*} [NormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] -variable {E'' : Type*} [NormedAddCommGroup E''] [InnerProductSpace 𝕜 E''] - -@[simp] -theorem Orthonormal.equiv_refl {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) : - hv.equiv hv (Equiv.refl ι) = LinearIsometryEquiv.refl 𝕜 E := - v.ext_linearIsometryEquiv fun i => by - simp only [Orthonormal.equiv_apply, Equiv.coe_refl, id, LinearIsometryEquiv.coe_refl] - -@[simp] -theorem Orthonormal.equiv_symm {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) {v' : Basis ι' 𝕜 E'} - (hv' : Orthonormal 𝕜 v') (e : ι ≃ ι') : (hv.equiv hv' e).symm = hv'.equiv hv e.symm := - v'.ext_linearIsometryEquiv fun i => - (hv.equiv hv' e).injective <| by - simp only [LinearIsometryEquiv.apply_symm_apply, Orthonormal.equiv_apply, e.apply_symm_apply] - -end - /-- The inner product of a nonzero vector with a nonzero multiple of itself, divided by the product of their norms, has absolute value 1. -/ @@ -1804,62 +1851,6 @@ theorem eq_of_norm_le_re_inner_eq_norm_sq {x y : E} (hle : ‖x‖ ≤ ‖y‖) have H₂ : re ⟪y, x⟫ = ‖y‖ ^ 2 := by rwa [← inner_conj_symm, conj_re] simpa [inner_sub_left, inner_sub_right, ← norm_sq_eq_inner, h, H₂] using H₁ -/-- The inner product of two weighted sums, where the weights in each -sum add to 0, in terms of the norms of pairwise differences. -/ -theorem inner_sum_smul_sum_smul_of_sum_eq_zero {ι₁ : Type*} {s₁ : Finset ι₁} {w₁ : ι₁ → ℝ} - (v₁ : ι₁ → F) (h₁ : ∑ i ∈ s₁, w₁ i = 0) {ι₂ : Type*} {s₂ : Finset ι₂} {w₂ : ι₂ → ℝ} - (v₂ : ι₂ → F) (h₂ : ∑ i ∈ s₂, w₂ i = 0) : - ⟪∑ i₁ ∈ s₁, w₁ i₁ • v₁ i₁, ∑ i₂ ∈ s₂, w₂ i₂ • v₂ i₂⟫_ℝ = - (-∑ i₁ ∈ s₁, ∑ i₂ ∈ s₂, w₁ i₁ * w₂ i₂ * (‖v₁ i₁ - v₂ i₂‖ * ‖v₁ i₁ - v₂ i₂‖)) / 2 := by - simp_rw [sum_inner, inner_sum, real_inner_smul_left, real_inner_smul_right, - real_inner_eq_norm_mul_self_add_norm_mul_self_sub_norm_sub_mul_self_div_two, ← div_sub_div_same, - ← div_add_div_same, mul_sub_left_distrib, left_distrib, Finset.sum_sub_distrib, - Finset.sum_add_distrib, ← Finset.mul_sum, ← Finset.sum_mul, h₁, h₂, zero_mul, - mul_zero, Finset.sum_const_zero, zero_add, zero_sub, Finset.mul_sum, neg_div, - Finset.sum_div, mul_div_assoc, mul_assoc] - -variable (𝕜) - -/-- `innerSL` is an isometry. Note that the associated `LinearIsometry` is defined in -`InnerProductSpace.Dual` as `toDualMap`. -/ -@[simp] -theorem innerSL_apply_norm (x : E) : ‖innerSL 𝕜 x‖ = ‖x‖ := by - refine - le_antisymm ((innerSL 𝕜 x).opNorm_le_bound (norm_nonneg _) fun y => norm_inner_le_norm _ _) ?_ - rcases eq_or_ne x 0 with (rfl | h) - · simp - · refine (mul_le_mul_right (norm_pos_iff.2 h)).mp ?_ - calc - ‖x‖ * ‖x‖ = ‖(⟪x, x⟫ : 𝕜)‖ := by - rw [← sq, inner_self_eq_norm_sq_to_K, norm_pow, norm_ofReal, abs_norm] - _ ≤ ‖innerSL 𝕜 x‖ * ‖x‖ := (innerSL 𝕜 x).le_opNorm _ - -lemma norm_innerSL_le : ‖innerSL 𝕜 (E := E)‖ ≤ 1 := - ContinuousLinearMap.opNorm_le_bound _ zero_le_one (by simp) - -variable {𝕜} - -/-- When an inner product space `E` over `𝕜` is considered as a real normed space, its inner -product satisfies `IsBoundedBilinearMap`. - -In order to state these results, we need a `NormedSpace ℝ E` instance. We will later establish -such an instance by restriction-of-scalars, `InnerProductSpace.rclikeToReal 𝕜 E`, but this -instance may be not definitionally equal to some other “natural” instance. So, we assume -`[NormedSpace ℝ E]`. --/ -theorem _root_.isBoundedBilinearMap_inner [NormedSpace ℝ E] : - IsBoundedBilinearMap ℝ fun p : E × E => ⟪p.1, p.2⟫ := - { add_left := inner_add_left - smul_left := fun r x y => by - simp only [← algebraMap_smul 𝕜 r x, algebraMap_eq_ofReal, inner_smul_real_left] - add_right := inner_add_right - smul_right := fun r x y => by - simp only [← algebraMap_smul 𝕜 r y, algebraMap_eq_ofReal, inner_smul_real_right] - bound := - ⟨1, zero_lt_one, fun x y => by - rw [one_mul] - exact norm_inner_le_norm x y⟩ } - end Norm section BesselsInequality @@ -2268,7 +2259,7 @@ end RCLikeToReal section Continuous -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -2283,6 +2274,7 @@ local postfix:90 "†" => starRingEnd _ theorem continuous_inner : Continuous fun p : E × E => ⟪p.1, p.2⟫ := letI : InnerProductSpace ℝ E := InnerProductSpace.rclikeToReal 𝕜 E + letI : IsScalarTower ℝ 𝕜 E := RestrictScalars.isScalarTower _ _ _ isBoundedBilinearMap_inner.continuous variable {α : Type*} @@ -2333,7 +2325,7 @@ end ReApplyInnerSelf section ReApplyInnerSelf_Seminormed -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -2355,7 +2347,7 @@ end ReApplyInnerSelf_Seminormed section UniformSpace.Completion -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y diff --git a/Mathlib/Analysis/InnerProductSpace/Symmetric.lean b/Mathlib/Analysis/InnerProductSpace/Symmetric.lean index 4928bc0cac733..0dafa0de1b246 100644 --- a/Mathlib/Analysis/InnerProductSpace/Symmetric.lean +++ b/Mathlib/Analysis/InnerProductSpace/Symmetric.lean @@ -36,11 +36,13 @@ open RCLike open ComplexConjugate +section Seminormed + variable {𝕜 E E' F G : Type*} [RCLike 𝕜] -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] -variable [NormedAddCommGroup F] [InnerProductSpace 𝕜 F] -variable [NormedAddCommGroup G] [InnerProductSpace 𝕜 G] -variable [NormedAddCommGroup E'] [InnerProductSpace ℝ E'] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup F] [InnerProductSpace 𝕜 F] +variable [SeminormedAddCommGroup G] [InnerProductSpace 𝕜 G] +variable [SeminormedAddCommGroup E'] [InnerProductSpace ℝ E'] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -83,23 +85,6 @@ theorem IsSymmetric.add {T S : E →ₗ[𝕜] E} (hT : T.IsSymmetric) (hS : S.Is rw [LinearMap.add_apply, inner_add_left, hT x y, hS x y, ← inner_add_right] rfl -/-- The **Hellinger--Toeplitz theorem**: if a symmetric operator is defined on a complete space, - then it is automatically continuous. -/ -theorem IsSymmetric.continuous [CompleteSpace E] {T : E →ₗ[𝕜] E} (hT : IsSymmetric T) : - Continuous T := by - -- We prove it by using the closed graph theorem - refine T.continuous_of_seq_closed_graph fun u x y hu hTu => ?_ - rw [← sub_eq_zero, ← @inner_self_eq_zero 𝕜] - have hlhs : ∀ k : ℕ, ⟪T (u k) - T x, y - T x⟫ = ⟪u k - x, T (y - T x)⟫ := by - intro k - rw [← T.map_sub, hT] - refine tendsto_nhds_unique ((hTu.sub_const _).inner tendsto_const_nhds) ?_ - simp_rw [Function.comp_apply, hlhs] - rw [← inner_zero_left (T (y - T x))] - refine Filter.Tendsto.inner ?_ tendsto_const_nhds - rw [← sub_self x] - exact hu.sub_const _ - /-- For a symmetric operator `T`, the function `fun x ↦ ⟪T x, x⟫` is real-valued. -/ @[simp] theorem IsSymmetric.coe_reApplyInnerSelf_apply {T : E →L[𝕜] E} (hT : IsSymmetric (T : E →ₗ[𝕜] E)) @@ -115,14 +100,14 @@ theorem IsSymmetric.restrict_invariant {T : E →ₗ[𝕜] E} (hT : IsSymmetric (hV : ∀ v ∈ V, T v ∈ V) : IsSymmetric (T.restrict hV) := fun v w => hT v w theorem IsSymmetric.restrictScalars {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) : - @LinearMap.IsSymmetric ℝ E _ _ (InnerProductSpace.rclikeToReal 𝕜 E) - (@LinearMap.restrictScalars ℝ 𝕜 _ _ _ _ _ _ (InnerProductSpace.rclikeToReal 𝕜 E).toModule - (InnerProductSpace.rclikeToReal 𝕜 E).toModule _ _ _ T) := + letI := InnerProductSpace.rclikeToReal 𝕜 E + letI : IsScalarTower ℝ 𝕜 E := RestrictScalars.isScalarTower _ _ _ + (T.restrictScalars ℝ).IsSymmetric := fun x y => by simp [hT x y, real_inner_eq_re_inner, LinearMap.coe_restrictScalars ℝ] section Complex -variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] +variable {V : Type*} [SeminormedAddCommGroup V] [InnerProductSpace ℂ V] attribute [local simp] map_ofNat in -- use `ofNat` simp theorem with bad keys open scoped InnerProductSpace in @@ -167,6 +152,39 @@ theorem IsSymmetric.inner_map_polarization {T : E →ₗ[𝕜] E} (hT : T.IsSymm sub_sub, ← mul_assoc, mul_neg, h, neg_neg, one_mul, neg_one_mul] ring +end LinearMap + +end Seminormed + +section Normed + +variable {𝕜 E E' F G : Type*} [RCLike 𝕜] +variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [NormedAddCommGroup F] [InnerProductSpace 𝕜 F] +variable [NormedAddCommGroup G] [InnerProductSpace 𝕜 G] +variable [NormedAddCommGroup E'] [InnerProductSpace ℝ E'] + +local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y + +namespace LinearMap + +/-- The **Hellinger--Toeplitz theorem**: if a symmetric operator is defined on a complete space, + then it is automatically continuous. -/ +theorem IsSymmetric.continuous [CompleteSpace E] {T : E →ₗ[𝕜] E} (hT : IsSymmetric T) : + Continuous T := by + -- We prove it by using the closed graph theorem + refine T.continuous_of_seq_closed_graph fun u x y hu hTu => ?_ + rw [← sub_eq_zero, ← @inner_self_eq_zero 𝕜] + have hlhs : ∀ k : ℕ, ⟪T (u k) - T x, y - T x⟫ = ⟪u k - x, T (y - T x)⟫ := by + intro k + rw [← T.map_sub, hT] + refine tendsto_nhds_unique ((hTu.sub_const _).inner tendsto_const_nhds) ?_ + simp_rw [Function.comp_apply, hlhs] + rw [← inner_zero_left (T (y - T x))] + refine Filter.Tendsto.inner ?_ tendsto_const_nhds + rw [← sub_self x] + exact hu.sub_const _ + /-- A symmetric linear map `T` is zero if and only if `⟪T x, x⟫_ℝ = 0` for all `x`. See `inner_map_self_eq_zero` for the complex version without the symmetric assumption. -/ theorem IsSymmetric.inner_map_self_eq_zero {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) : @@ -178,3 +196,5 @@ theorem IsSymmetric.inner_map_self_eq_zero {T : E →ₗ[𝕜] E} (hT : T.IsSymm ring end LinearMap + +end Normed diff --git a/Mathlib/Analysis/Normed/Module/Completion.lean b/Mathlib/Analysis/Normed/Module/Completion.lean index 451aed37e833c..bb143e6302377 100644 --- a/Mathlib/Analysis/Normed/Module/Completion.lean +++ b/Mathlib/Analysis/Normed/Module/Completion.lean @@ -27,7 +27,7 @@ namespace UniformSpace namespace Completion -variable (𝕜 E : Type*) [NormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] +variable (𝕜 E : Type*) [NormedField 𝕜] [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] instance (priority := 100) NormedSpace.to_uniformContinuousConstSMul : UniformContinuousConstSMul 𝕜 E := From 88787b217c3255058d0046f800a349f773ce27b2 Mon Sep 17 00:00:00 2001 From: Jiang Jiedong Date: Wed, 25 Sep 2024 21:17:42 +0000 Subject: [PATCH 154/170] feat(FieldTheory/Minpoly): remove `IsIntegral` condition for lemmas (#17080) Remove `IsIntegral` condition for `minpoly.add_algebraMap` and `minpoly.sub_algebraMap`. --- Mathlib/FieldTheory/Minpoly/Field.lean | 32 +++++++++++-------- .../Cyclotomic/PrimitiveRoots.lean | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Mathlib/FieldTheory/Minpoly/Field.lean b/Mathlib/FieldTheory/Minpoly/Field.lean index 32d3a549998d0..b62efc1339b8a 100644 --- a/Mathlib/FieldTheory/Minpoly/Field.lean +++ b/Mathlib/FieldTheory/Minpoly/Field.lean @@ -127,22 +127,26 @@ theorem eq_of_irreducible [Nontrivial B] {p : A[X]} (hp1 : Irreducible p) · rw [aeval_mul, hp2, zero_mul] · rwa [Polynomial.Monic, leadingCoeff_mul, leadingCoeff_C, mul_inv_cancel₀] -theorem add_algebraMap {B : Type*} [CommRing B] [Algebra A B] {x : B} (hx : IsIntegral A x) +theorem add_algebraMap {B : Type*} [CommRing B] [Algebra A B] (x : B) (a : A) : minpoly A (x + algebraMap A B a) = (minpoly A x).comp (X - C a) := by - refine (minpoly.unique _ _ ((minpoly.monic hx).comp_X_sub_C _) ?_ fun q qmo hq => ?_).symm - · simp [aeval_comp] - · have : (Polynomial.aeval x) (q.comp (X + C a)) = 0 := by simpa [aeval_comp] using hq - have H := minpoly.min A x (qmo.comp_X_add_C _) this - rw [degree_eq_natDegree qmo.ne_zero, - degree_eq_natDegree ((minpoly.monic hx).comp_X_sub_C _).ne_zero, natDegree_comp, - natDegree_X_sub_C, mul_one] - rwa [degree_eq_natDegree (minpoly.ne_zero hx), - degree_eq_natDegree (qmo.comp_X_add_C _).ne_zero, natDegree_comp, - natDegree_X_add_C, mul_one] at H - -theorem sub_algebraMap {B : Type*} [CommRing B] [Algebra A B] {x : B} (hx : IsIntegral A x) + by_cases hx : IsIntegral A x + · refine (minpoly.unique _ _ ((minpoly.monic hx).comp_X_sub_C _) ?_ fun q qmo hq => ?_).symm + · simp [aeval_comp] + · have : (Polynomial.aeval x) (q.comp (X + C a)) = 0 := by simpa [aeval_comp] using hq + have H := minpoly.min A x (qmo.comp_X_add_C _) this + rw [degree_eq_natDegree qmo.ne_zero, + degree_eq_natDegree ((minpoly.monic hx).comp_X_sub_C _).ne_zero, natDegree_comp, + natDegree_X_sub_C, mul_one] + rwa [degree_eq_natDegree (minpoly.ne_zero hx), + degree_eq_natDegree (qmo.comp_X_add_C _).ne_zero, natDegree_comp, + natDegree_X_add_C, mul_one] at H + · rw [minpoly.eq_zero hx, minpoly.eq_zero, zero_comp] + refine fun h ↦ hx ?_ + simpa only [add_sub_cancel_right] using IsIntegral.sub h (isIntegral_algebraMap (x := a)) + +theorem sub_algebraMap {B : Type*} [CommRing B] [Algebra A B] {x : B} (a : A) : minpoly A (x - algebraMap A B a) = (minpoly A x).comp (X + C a) := by - simpa [sub_eq_add_neg] using add_algebraMap hx (-a) + simpa [sub_eq_add_neg] using add_algebraMap x (-a) section AlgHomFintype diff --git a/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean b/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean index e8b1549b25e66..33bb6cad832cd 100644 --- a/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean +++ b/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean @@ -379,7 +379,7 @@ theorem minpoly_sub_one_eq_cyclotomic_comp [Algebra K A] [IsDomain A] {ζ : A} minpoly K (ζ - 1) = (cyclotomic n K).comp (X + 1) := by haveI := IsCyclotomicExtension.neZero' n K A rw [show ζ - 1 = ζ + algebraMap K A (-1) by simp [sub_eq_add_neg], - minpoly.add_algebraMap ((integral {n} K A).isIntegral ζ), + minpoly.add_algebraMap ζ, hζ.minpoly_eq_cyclotomic_of_irreducible h] simp From 34e653f6260189460db5f9fa6654eefde2f4fe8e Mon Sep 17 00:00:00 2001 From: Dagur Asgeirsson Date: Wed, 25 Sep 2024 22:30:40 +0000 Subject: [PATCH 155/170] chore(Condensed): shorten some names (#17075) Co-authored-by: Eric Wieser --- .../Condensed/Discrete/LocallyConstant.lean | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Mathlib/Condensed/Discrete/LocallyConstant.lean b/Mathlib/Condensed/Discrete/LocallyConstant.lean index 56e2cdc31aca0..ca028c4a70293 100644 --- a/Mathlib/Condensed/Discrete/LocallyConstant.lean +++ b/Mathlib/Condensed/Discrete/LocallyConstant.lean @@ -186,8 +186,7 @@ def componentHom (a : Fiber (f.comap g)) : simp only [Fiber.mk, Set.mem_preimage, Set.mem_singleton_iff] convert map_eq_image _ _ x exact map_preimage_eq_image_map _ _ a⟩ - continuous_toFun := by - exact Continuous.subtype_mk (Continuous.comp g.continuous continuous_subtype_val) _ + continuous_toFun := by exact Continuous.subtype_mk (g.continuous.comp continuous_subtype_val) _ -- term mode gives "unknown free variable" error. lemma incl_comap {S T : (CompHausLike P)ᵒᵖ} @@ -221,31 +220,30 @@ variable (P) (X : TopCat.{max u w}) (hs : ∀ ⦃X Y : CompHausLike P⦄ (f : X ⟶ Y), EffectiveEpi f → Function.Surjective f) /-- `locallyConstantIsoContinuousMap` is a natural isomorphism. -/ -noncomputable def functorToPresheavesIsoTopCatToSheafCompHausLike (X : Type (max u w)) : - functorToPresheaves.{u, w}.obj X ≅ - ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).val := +noncomputable def functorToPresheavesIso (X : Type (max u w)) : + functorToPresheaves.{u, w}.obj X ≅ ((TopCat.discrete.obj X).toSheafCompHausLike P hs).val := NatIso.ofComponents (fun S ↦ locallyConstantIsoContinuousMap _ _) /-- `CompHausLike.LocallyConstant.functorToPresheaves` lands in sheaves. -/ @[simps] def functor : - have := CompHausLike.preregular hs + haveI := CompHausLike.preregular hs Type (max u w) ⥤ Sheaf (coherentTopology (CompHausLike.{u} P)) (Type (max u w)) where obj X := { val := functorToPresheaves.{u, w}.obj X cond := by - rw [Presheaf.isSheaf_of_iso_iff (functorToPresheavesIsoTopCatToSheafCompHausLike P hs X)] - exact ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).cond } + rw [Presheaf.isSheaf_of_iso_iff (functorToPresheavesIso P hs X)] + exact ((TopCat.discrete.obj X).toSheafCompHausLike P hs).cond } map f := ⟨functorToPresheaves.{u, w}.map f⟩ /-- `CompHausLike.LocallyConstant.functor` is naturally isomorphic to the restriction of `topCatToSheafCompHausLike` to discrete topological spaces. -/ -noncomputable def functorIsoTopCatToSheafCompHausLike : +noncomputable def functorIso : functor.{u, w} P hs ≅ TopCat.discrete.{max w u} ⋙ topCatToSheafCompHausLike P hs := NatIso.ofComponents (fun X ↦ (fullyFaithfulSheafToPresheaf _ _).preimageIso - (functorToPresheavesIsoTopCatToSheafCompHausLike P hs X)) + (functorToPresheavesIso P hs X)) /-- The counit is natural in both `S : CompHausLike P` and `Y : Sheaf (coherentTopology (CompHausLike P)) (Type (max u w))` -/ From 4e3fd1ae9518ed2894bfc00592c81a3ee2b6180e Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:03:37 +0000 Subject: [PATCH 156/170] chore: update Mathlib dependencies 2024-09-25 (#17143) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index 0cedc34894a16..f82a37b5c0c11 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "6d5e1c81277e960372c94f19172440e39b3c5980", + "rev": "c57ab80c8dd20b345b29c81c446c78a6b3677d20", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 3874c4e1905a870816d44fb4873869a99637ed73 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 26 Sep 2024 00:13:21 +0000 Subject: [PATCH 157/170] feat: generalize normed instances on `UniformSpace.Completion` (#17059) Notably, `NormedSpace.to_uniformContinuousConstSMul` is generalized to `BoundedSMul` on `PseudoMetricSpace`s, relaxing the scalar considerably from normed fields. Co-authored-by: Eric Wieser --- .../Analysis/Normed/Module/Completion.lean | 78 ++++++++----------- Mathlib/Analysis/Normed/MulAction.lean | 1 + .../PiTensorProduct/InjectiveSeminorm.lean | 3 +- Mathlib/Topology/MetricSpace/Algebra.lean | 6 ++ Mathlib/Topology/MetricSpace/Completion.lean | 23 ++++++ 5 files changed, 64 insertions(+), 47 deletions(-) diff --git a/Mathlib/Analysis/Normed/Module/Completion.lean b/Mathlib/Analysis/Normed/Module/Completion.lean index bb143e6302377..c4377b5b2a68a 100644 --- a/Mathlib/Analysis/Normed/Module/Completion.lean +++ b/Mathlib/Analysis/Normed/Module/Completion.lean @@ -27,20 +27,16 @@ namespace UniformSpace namespace Completion -variable (𝕜 E : Type*) [NormedField 𝕜] [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] +variable (𝕜 E : Type*) -instance (priority := 100) NormedSpace.to_uniformContinuousConstSMul : - UniformContinuousConstSMul 𝕜 E := - ⟨fun c => (lipschitzWith_smul c).uniformContinuous⟩ +instance [NormedField 𝕜] [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] : + NormedSpace 𝕜 (Completion E) where + norm_smul_le := norm_smul_le -instance : NormedSpace 𝕜 (Completion E) := - { Completion.instModule with - norm_smul_le := fun c x => - induction_on x - (isClosed_le (continuous_const_smul _).norm (continuous_const.mul continuous_norm)) fun y => - by simp only [← coe_smul, norm_coe, norm_smul, le_rfl] } +section Module variable {𝕜 E} +variable [Semiring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] [UniformContinuousConstSMul 𝕜 E] /-- Embedding of a normed space to its completion as a linear isometry. -/ def toComplₗᵢ : E →ₗᵢ[𝕜] Completion E := @@ -66,46 +62,38 @@ theorem norm_toComplL {𝕜 E : Type*} [NontriviallyNormedField 𝕜] [NormedAdd [NormedSpace 𝕜 E] [Nontrivial E] : ‖(toComplL : E →L[𝕜] Completion E)‖ = 1 := (toComplₗᵢ : E →ₗᵢ[𝕜] Completion E).norm_toContinuousLinearMap +end Module + section Algebra -variable (𝕜) (A : Type*) - -instance [SeminormedRing A] : NormedRing (Completion A) := - { Completion.ring, - Completion.instMetricSpace with - dist_eq := fun x y => by - refine Completion.induction_on₂ x y ?_ ?_ <;> clear x y - · refine isClosed_eq (Completion.uniformContinuous_extension₂ _).continuous ?_ - exact Continuous.comp Completion.continuous_extension continuous_sub - · intro x y - rw [← Completion.coe_sub, norm_coe, Completion.dist_eq, dist_eq_norm] - norm_mul := fun x y => by - refine Completion.induction_on₂ x y ?_ ?_ <;> clear x y - · exact - isClosed_le (Continuous.comp continuous_norm continuous_mul) - (Continuous.comp _root_.continuous_mul - (Continuous.prod_map continuous_norm continuous_norm)) - · intro x y - simp only [← coe_mul, norm_coe] - exact norm_mul_le x y } - -instance [SeminormedCommRing A] [NormedAlgebra 𝕜 A] [UniformContinuousConstSMul 𝕜 A] : - NormedAlgebra 𝕜 (Completion A) := - { Completion.algebra A 𝕜 with - norm_smul_le := fun r x => by - refine Completion.induction_on x ?_ ?_ <;> clear x - · exact - isClosed_le (Continuous.comp continuous_norm (continuous_const_smul r)) - (Continuous.comp (continuous_mul_left _) continuous_norm) - · intro x - simp only [← coe_smul, norm_coe] - exact norm_smul_le r x } +variable (A : Type*) + +instance [SeminormedRing A] : NormedRing (Completion A) where + __ : NormedAddCommGroup (Completion A) := inferInstance + __ : Ring (Completion A) := inferInstance + norm_mul x y := by + induction x, y using induction_on₂ with + | hp => + exact + isClosed_le (Continuous.comp continuous_norm continuous_mul) + (Continuous.comp _root_.continuous_mul + (Continuous.prod_map continuous_norm continuous_norm)) + | ih x y => + simp only [← coe_mul, norm_coe] + exact norm_mul_le x y + +instance [SeminormedCommRing A] : NormedCommRing (Completion A) where + __ : CommRing (Completion A) := inferInstance + __ : NormedRing (Completion A) := inferInstance + +instance [NormedField 𝕜] [SeminormedCommRing A] [NormedAlgebra 𝕜 A] : + NormedAlgebra 𝕜 (Completion A) where + norm_smul_le := norm_smul_le instance [NormedField A] [CompletableTopField A] : NormedField (UniformSpace.Completion A) where - dist_eq x y := by - refine induction_on₂ x y ?_ (by simp [← coe_sub, dist_eq_norm]) - exact isClosed_eq (uniformContinuous_extension₂ _).continuous (by fun_prop) + __ : NormedCommRing (Completion A) := inferInstance + __ : Field (Completion A) := inferInstance norm_mul' x y := induction_on₂ x y (isClosed_eq (by fun_prop) (by fun_prop)) (by simp [← coe_mul]) end Algebra diff --git a/Mathlib/Analysis/Normed/MulAction.lean b/Mathlib/Analysis/Normed/MulAction.lean index 1c42cc236b1e9..2c9c706fdb6c1 100644 --- a/Mathlib/Analysis/Normed/MulAction.lean +++ b/Mathlib/Analysis/Normed/MulAction.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Topology.MetricSpace.Algebra +import Mathlib.Topology.Algebra.UniformMulAction /-! # Lemmas for `BoundedSMul` over normed additive groups diff --git a/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean b/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean index 1ddd022c490b2..299585582989c 100644 --- a/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean +++ b/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean @@ -211,8 +211,7 @@ theorem injectiveSeminorm_le_projectiveSeminorm : existsi PUnit, inferInstance, inferInstance ext x simp only [Seminorm.zero_apply, Seminorm.comp_apply, coe_normSeminorm] - have heq : toDualContinuousMultilinearMap PUnit x = 0 := by ext _ - rw [heq, norm_zero] + rw [Subsingleton.elim (toDualContinuousMultilinearMap PUnit x) 0, norm_zero] · intro p hp simp only [Set.mem_setOf_eq] at hp obtain ⟨G, _, _, h⟩ := hp diff --git a/Mathlib/Topology/MetricSpace/Algebra.lean b/Mathlib/Topology/MetricSpace/Algebra.lean index c2d744b24f070..724512392f31b 100644 --- a/Mathlib/Topology/MetricSpace/Algebra.lean +++ b/Mathlib/Topology/MetricSpace/Algebra.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Heather Macbeth -/ import Mathlib.Topology.Algebra.MulAction +import Mathlib.Topology.Algebra.UniformMulAction import Mathlib.Topology.MetricSpace.Lipschitz /-! @@ -143,6 +144,11 @@ instance (priority := 100) BoundedSMul.continuousSMul : ContinuousSMul α β whe gcongr _ < ε := hδε +instance (priority := 100) BoundedSMul.toUniformContinuousConstSMul : + UniformContinuousConstSMul α β := + ⟨fun c => ((lipschitzWith_iff_dist_le_mul (K := nndist c 0)).2 fun _ _ => + dist_smul_pair c _ _).uniformContinuous⟩ + -- this instance could be deduced from `NormedSpace.boundedSMul`, but we prove it separately -- here so that it is available earlier in the hierarchy instance Real.boundedSMul : BoundedSMul ℝ ℝ where diff --git a/Mathlib/Topology/MetricSpace/Completion.lean b/Mathlib/Topology/MetricSpace/Completion.lean index 1ffdfa1fba1b7..97c5f07d31c6e 100644 --- a/Mathlib/Topology/MetricSpace/Completion.lean +++ b/Mathlib/Topology/MetricSpace/Completion.lean @@ -6,6 +6,8 @@ Authors: Sébastien Gouëzel import Mathlib.Topology.UniformSpace.Completion import Mathlib.Topology.MetricSpace.Isometry import Mathlib.Topology.MetricSpace.Lipschitz +import Mathlib.Topology.MetricSpace.Algebra +import Mathlib.Topology.Algebra.GroupCompletion import Mathlib.Topology.Instances.Real /-! @@ -168,6 +170,27 @@ theorem coe_isometry : Isometry ((↑) : α → Completion α) := protected theorem edist_eq (x y : α) : edist (x : Completion α) y = edist x y := coe_isometry x y +instance {M} [Zero M] [Zero α] [SMul M α] [PseudoMetricSpace M] [BoundedSMul M α] : + BoundedSMul M (Completion α) where + dist_smul_pair' c x₁ x₂ := by + induction x₁, x₂ using induction_on₂ with + | hp => + exact isClosed_le + ((continuous_fst.const_smul _).dist (continuous_snd.const_smul _)) + (continuous_const.mul (continuous_fst.dist continuous_snd)) + | ih x₁ x₂ => + rw [← coe_smul, ← coe_smul, Completion.dist_eq, Completion.dist_eq] + exact dist_smul_pair c x₁ x₂ + dist_pair_smul' c₁ c₂ x := by + induction x using induction_on with + | hp => + exact isClosed_le + ((continuous_const_smul _).dist (continuous_const_smul _)) + (continuous_const.mul (continuous_id.dist continuous_const)) + | ih x => + rw [← coe_smul, ← coe_smul, Completion.dist_eq, ← coe_zero, Completion.dist_eq] + exact dist_pair_smul c₁ c₂ x + end UniformSpace.Completion open UniformSpace Completion NNReal From 9678fd7fe516e300382ea1c0dfec4cab4700b340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 26 Sep 2024 00:42:50 +0000 Subject: [PATCH 158/170] chore: split Algebra.Bounds and Algebra.Order.Pointwise (#16986) Delete `Algebra.Bounds` and `Algebra.Order.Pointwise`. Create * `Algebra.Order.Field.Pointwise` for lemmas about pointwise operations in linear ordered fields * `Algebra.Order.Group.CompleteLattice` for distributivity of group operations over supremum/infimum * `Algebra.Order.Group.Pointwise.Bounds` for boundedness of pointwise-defined sets * `Algebra.Order.Group.Pointwise.CompleteLattice` for lemmas about the supremum/infimum of pointwise-defined sets. --- Mathlib.lean | 6 +- Mathlib/Algebra/Bounds.lean | 167 ------------ Mathlib/Algebra/Order/CompleteField.lean | 2 +- Mathlib/Algebra/Order/Field/Pointwise.lean | 126 +++++++++ .../Algebra/Order/Group/CompleteLattice.lean | 49 ++++ .../Algebra/Order/Group/Pointwise/Bounds.lean | 117 ++++++++ .../Group/Pointwise/CompleteLattice.lean | 117 ++++++++ Mathlib/Algebra/Order/Pointwise.lean | 250 ------------------ Mathlib/Data/Real/Archimedean.lean | 2 +- .../Constructions/HaarToSphere.lean | 2 +- 10 files changed, 416 insertions(+), 422 deletions(-) delete mode 100644 Mathlib/Algebra/Bounds.lean create mode 100644 Mathlib/Algebra/Order/Field/Pointwise.lean create mode 100644 Mathlib/Algebra/Order/Group/CompleteLattice.lean create mode 100644 Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean create mode 100644 Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean delete mode 100644 Mathlib/Algebra/Order/Pointwise.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2f1502803917a..8f564f4f1e5de 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -56,7 +56,6 @@ import Mathlib.Algebra.BigOperators.Ring.Multiset import Mathlib.Algebra.BigOperators.Ring.Nat import Mathlib.Algebra.BigOperators.RingEquiv import Mathlib.Algebra.BigOperators.WithTop -import Mathlib.Algebra.Bounds import Mathlib.Algebra.Category.AlgebraCat.Basic import Mathlib.Algebra.Category.AlgebraCat.Limits import Mathlib.Algebra.Category.AlgebraCat.Monoidal @@ -566,6 +565,7 @@ import Mathlib.Algebra.Order.Field.Canonical.Defs import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.Field.InjSurj import Mathlib.Algebra.Order.Field.Pi +import Mathlib.Algebra.Order.Field.Pointwise import Mathlib.Algebra.Order.Field.Power import Mathlib.Algebra.Order.Field.Rat import Mathlib.Algebra.Order.Field.Subfield @@ -577,6 +577,7 @@ import Mathlib.Algebra.Order.Group.Action import Mathlib.Algebra.Order.Group.Action.Synonym import Mathlib.Algebra.Order.Group.Basic import Mathlib.Algebra.Order.Group.Bounds +import Mathlib.Algebra.Order.Group.CompleteLattice import Mathlib.Algebra.Order.Group.Cone import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Group.DenselyOrdered @@ -589,6 +590,8 @@ import Mathlib.Algebra.Order.Group.MinMax import Mathlib.Algebra.Order.Group.Nat import Mathlib.Algebra.Order.Group.OrderIso import Mathlib.Algebra.Order.Group.PiLex +import Mathlib.Algebra.Order.Group.Pointwise.Bounds +import Mathlib.Algebra.Order.Group.Pointwise.CompleteLattice import Mathlib.Algebra.Order.Group.PosPart import Mathlib.Algebra.Order.Group.Prod import Mathlib.Algebra.Order.Group.Synonym @@ -644,7 +647,6 @@ import Mathlib.Algebra.Order.Nonneg.Floor import Mathlib.Algebra.Order.Nonneg.Module import Mathlib.Algebra.Order.Nonneg.Ring import Mathlib.Algebra.Order.Pi -import Mathlib.Algebra.Order.Pointwise import Mathlib.Algebra.Order.Positive.Field import Mathlib.Algebra.Order.Positive.Ring import Mathlib.Algebra.Order.Rearrangement diff --git a/Mathlib/Algebra/Bounds.lean b/Mathlib/Algebra/Bounds.lean deleted file mode 100644 index 8c9ff1cb53079..0000000000000 --- a/Mathlib/Algebra/Bounds.lean +++ /dev/null @@ -1,167 +0,0 @@ -/- -Copyright (c) 2021 Yury Kudryashov. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yury Kudryashov --/ -import Mathlib.Algebra.Group.Pointwise.Set -import Mathlib.Algebra.Order.Group.OrderIso -import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual -import Mathlib.Order.Bounds.OrderIso -import Mathlib.Order.ConditionallyCompleteLattice.Basic - -/-! -# Upper/lower bounds in ordered monoids and groups - -In this file we prove a few facts like “`-s` is bounded above iff `s` is bounded below” -(`bddAbove_neg`). --/ - - -open Function Set - -open Pointwise - -section InvNeg - -variable {G : Type*} [Group G] [Preorder G] [CovariantClass G G (· * ·) (· ≤ ·)] - [CovariantClass G G (swap (· * ·)) (· ≤ ·)] {s : Set G} {a : G} - -@[to_additive (attr := simp)] -theorem bddAbove_inv : BddAbove s⁻¹ ↔ BddBelow s := - (OrderIso.inv G).bddAbove_preimage - -@[to_additive (attr := simp)] -theorem bddBelow_inv : BddBelow s⁻¹ ↔ BddAbove s := - (OrderIso.inv G).bddBelow_preimage - -@[to_additive] -theorem BddAbove.inv (h : BddAbove s) : BddBelow s⁻¹ := - bddBelow_inv.2 h - -@[to_additive] -theorem BddBelow.inv (h : BddBelow s) : BddAbove s⁻¹ := - bddAbove_inv.2 h - -@[to_additive (attr := simp)] -theorem isLUB_inv : IsLUB s⁻¹ a ↔ IsGLB s a⁻¹ := - (OrderIso.inv G).isLUB_preimage - -@[to_additive] -theorem isLUB_inv' : IsLUB s⁻¹ a⁻¹ ↔ IsGLB s a := - (OrderIso.inv G).isLUB_preimage' - -@[to_additive] -theorem IsGLB.inv (h : IsGLB s a) : IsLUB s⁻¹ a⁻¹ := - isLUB_inv'.2 h - -@[to_additive (attr := simp)] -theorem isGLB_inv : IsGLB s⁻¹ a ↔ IsLUB s a⁻¹ := - (OrderIso.inv G).isGLB_preimage - -@[to_additive] -theorem isGLB_inv' : IsGLB s⁻¹ a⁻¹ ↔ IsLUB s a := - (OrderIso.inv G).isGLB_preimage' - -@[to_additive] -theorem IsLUB.inv (h : IsLUB s a) : IsGLB s⁻¹ a⁻¹ := - isGLB_inv'.2 h - -@[to_additive] -lemma BddBelow.range_inv {α : Type*} {f : α → G} (hf : BddBelow (range f)) : - BddAbove (range (fun x => (f x)⁻¹)) := - hf.range_comp (OrderIso.inv G).monotone - -@[to_additive] -lemma BddAbove.range_inv {α : Type*} {f : α → G} (hf : BddAbove (range f)) : - BddBelow (range (fun x => (f x)⁻¹)) := - BddBelow.range_inv (G := Gᵒᵈ) hf - -end InvNeg - -section mul_add - -variable {M : Type*} [Mul M] [Preorder M] [CovariantClass M M (· * ·) (· ≤ ·)] - [CovariantClass M M (swap (· * ·)) (· ≤ ·)] - -@[to_additive] -theorem mul_mem_upperBounds_mul {s t : Set M} {a b : M} (ha : a ∈ upperBounds s) - (hb : b ∈ upperBounds t) : a * b ∈ upperBounds (s * t) := - forall_image2_iff.2 fun _ hx _ hy => mul_le_mul' (ha hx) (hb hy) - -@[to_additive] -theorem subset_upperBounds_mul (s t : Set M) : - upperBounds s * upperBounds t ⊆ upperBounds (s * t) := - image2_subset_iff.2 fun _ hx _ hy => mul_mem_upperBounds_mul hx hy - -@[to_additive] -theorem mul_mem_lowerBounds_mul {s t : Set M} {a b : M} (ha : a ∈ lowerBounds s) - (hb : b ∈ lowerBounds t) : a * b ∈ lowerBounds (s * t) := - mul_mem_upperBounds_mul (M := Mᵒᵈ) ha hb - -@[to_additive] -theorem subset_lowerBounds_mul (s t : Set M) : - lowerBounds s * lowerBounds t ⊆ lowerBounds (s * t) := - subset_upperBounds_mul (M := Mᵒᵈ) _ _ - -@[to_additive] -theorem BddAbove.mul {s t : Set M} (hs : BddAbove s) (ht : BddAbove t) : BddAbove (s * t) := - (Nonempty.mul hs ht).mono (subset_upperBounds_mul s t) - -@[to_additive] -theorem BddBelow.mul {s t : Set M} (hs : BddBelow s) (ht : BddBelow t) : BddBelow (s * t) := - (Nonempty.mul hs ht).mono (subset_lowerBounds_mul s t) - -@[to_additive] -lemma BddAbove.range_mul {α : Type*} {f g : α → M} (hf : BddAbove (range f)) - (hg : BddAbove (range g)) : BddAbove (range (fun x => f x * g x)) := - BddAbove.range_comp (f := fun x => (⟨f x, g x⟩ : M × M)) - (bddAbove_range_prod.mpr ⟨hf, hg⟩) (Monotone.mul' monotone_fst monotone_snd) - -@[to_additive] -lemma BddBelow.range_mul {α : Type*} {f g : α → M} (hf : BddBelow (range f)) - (hg : BddBelow (range g)) : BddBelow (range (fun x => f x * g x)) := - BddAbove.range_mul (M := Mᵒᵈ) hf hg - -end mul_add - -section ConditionallyCompleteLattice - -section Right - -variable {ι G : Type*} [Group G] [ConditionallyCompleteLattice G] - [CovariantClass G G (Function.swap (· * ·)) (· ≤ ·)] [Nonempty ι] {f : ι → G} - -@[to_additive] -theorem ciSup_mul (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) * a = ⨆ i, f i * a := - (OrderIso.mulRight a).map_ciSup hf - -@[to_additive] -theorem ciSup_div (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) / a = ⨆ i, f i / a := by - simp only [div_eq_mul_inv, ciSup_mul hf] - -@[to_additive] -theorem ciInf_mul (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) * a = ⨅ i, f i * a := - (OrderIso.mulRight a).map_ciInf hf - -@[to_additive] -theorem ciInf_div (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) / a = ⨅ i, f i / a := by - simp only [div_eq_mul_inv, ciInf_mul hf] - -end Right - -section Left - -variable {ι : Sort*} {G : Type*} [Group G] [ConditionallyCompleteLattice G] - [CovariantClass G G (· * ·) (· ≤ ·)] [Nonempty ι] {f : ι → G} - -@[to_additive] -theorem mul_ciSup (hf : BddAbove (range f)) (a : G) : (a * ⨆ i, f i) = ⨆ i, a * f i := - (OrderIso.mulLeft a).map_ciSup hf - -@[to_additive] -theorem mul_ciInf (hf : BddBelow (range f)) (a : G) : (a * ⨅ i, f i) = ⨅ i, a * f i := - (OrderIso.mulLeft a).map_ciInf hf - -end Left - -end ConditionallyCompleteLattice diff --git a/Mathlib/Algebra/Order/CompleteField.lean b/Mathlib/Algebra/Order/CompleteField.lean index 2c8942e53c15c..680ebceb3f631 100644 --- a/Mathlib/Algebra/Order/CompleteField.lean +++ b/Mathlib/Algebra/Order/CompleteField.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex J. Best, Yaël Dillies -/ import Mathlib.Algebra.Order.Archimedean.Hom -import Mathlib.Algebra.Order.Pointwise +import Mathlib.Algebra.Order.Group.Pointwise.CompleteLattice import Mathlib.Analysis.SpecialFunctions.Pow.Real /-! diff --git a/Mathlib/Algebra/Order/Field/Pointwise.lean b/Mathlib/Algebra/Order/Field/Pointwise.lean new file mode 100644 index 0000000000000..8f2b1867f0d73 --- /dev/null +++ b/Mathlib/Algebra/Order/Field/Pointwise.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2021 Alex J. Best. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Alex J. Best, Yaël Dillies +-/ +import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Order.Field.Basic +import Mathlib.Algebra.SMulWithZero + +/-! +# Pointwise operations on ordered algebraic objects + +This file contains lemmas about the effect of pointwise operations on sets with an order structure. +-/ + +open Function Set +open scoped Pointwise + +variable {α : Type*} + +namespace LinearOrderedField + +variable {K : Type*} [LinearOrderedField K] {a b r : K} (hr : 0 < r) +include hr + +theorem smul_Ioo : r • Ioo a b = Ioo (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioo] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_lt_mul_left hr).mpr a_h_left_left + · exact (mul_lt_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(lt_div_iff' hr).mpr a_left, (div_lt_iff' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Icc : r • Icc a b = Icc (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Icc] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_le_mul_left hr).mpr a_h_left_left + · exact (mul_le_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Ico : r • Ico a b = Ico (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ico] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_le_mul_left hr).mpr a_h_left_left + · exact (mul_lt_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_lt_iff' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Ioc : r • Ioc a b = Ioc (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioc] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_lt_mul_left hr).mpr a_h_left_left + · exact (mul_le_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(lt_div_iff' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Ioi : r • Ioi a = Ioi (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioi] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_lt_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (lt_div_iff' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +theorem smul_Iio : r • Iio a = Iio (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Iio] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_lt_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (div_lt_iff' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +theorem smul_Ici : r • Ici a = Ici (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioi] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_le_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (le_div_iff₀' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +theorem smul_Iic : r • Iic a = Iic (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Iio] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_le_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (div_le_iff₀' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +end LinearOrderedField diff --git a/Mathlib/Algebra/Order/Group/CompleteLattice.lean b/Mathlib/Algebra/Order/Group/CompleteLattice.lean new file mode 100644 index 0000000000000..19c8f5fda8e68 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/CompleteLattice.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2021 Yury G. Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury G. Kudryashov +-/ +import Mathlib.Algebra.Order.Group.OrderIso +import Mathlib.Order.ConditionallyCompleteLattice.Basic + +/-! +# Distributivity of group operations over supremum/infimum +-/ + +open Function Set + +variable {ι G : Type*} [Group G] [ConditionallyCompleteLattice G] [Nonempty ι] {f : ι → G} + +section Right +variable [CovariantClass G G (swap (· * ·)) (· ≤ ·)] + +@[to_additive] +lemma ciSup_mul (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) * a = ⨆ i, f i * a := + (OrderIso.mulRight a).map_ciSup hf + +@[to_additive] +lemma ciSup_div (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) / a = ⨆ i, f i / a := by + simp only [div_eq_mul_inv, ciSup_mul hf] + +@[to_additive] +lemma ciInf_mul (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) * a = ⨅ i, f i * a := + (OrderIso.mulRight a).map_ciInf hf + +@[to_additive] +lemma ciInf_div (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) / a = ⨅ i, f i / a := by + simp only [div_eq_mul_inv, ciInf_mul hf] + +end Right + +section Left +variable [CovariantClass G G (· * ·) (· ≤ ·)] + +@[to_additive] +lemma mul_ciSup (hf : BddAbove (range f)) (a : G) : (a * ⨆ i, f i) = ⨆ i, a * f i := + (OrderIso.mulLeft a).map_ciSup hf + +@[to_additive] +lemma mul_ciInf (hf : BddBelow (range f)) (a : G) : (a * ⨅ i, f i) = ⨅ i, a * f i := + (OrderIso.mulLeft a).map_ciInf hf + +end Left diff --git a/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean b/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean new file mode 100644 index 0000000000000..e6a5407931b80 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2021 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Order.Group.OrderIso +import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual +import Mathlib.Order.Bounds.OrderIso + +/-! +# Upper/lower bounds in ordered monoids and groups + +In this file we prove a few facts like “`-s` is bounded above iff `s` is bounded below” +(`bddAbove_neg`). +-/ + +open Function Set +open scoped Pointwise + +variable {ι G M : Type*} + +section Mul +variable [Mul M] [Preorder M] [CovariantClass M M (· * ·) (· ≤ ·)] + [CovariantClass M M (swap (· * ·)) (· ≤ ·)] {f g : ι → M} {s t : Set M} {a b : M} + +@[to_additive] +lemma mul_mem_upperBounds_mul (ha : a ∈ upperBounds s) (hb : b ∈ upperBounds t) : + a * b ∈ upperBounds (s * t) := forall_image2_iff.2 fun _ hx _ hy => mul_le_mul' (ha hx) (hb hy) + +@[to_additive] +lemma subset_upperBounds_mul (s t : Set M) : upperBounds s * upperBounds t ⊆ upperBounds (s * t) := + image2_subset_iff.2 fun _ hx _ hy => mul_mem_upperBounds_mul hx hy + +@[to_additive] +lemma mul_mem_lowerBounds_mul (ha : a ∈ lowerBounds s) (hb : b ∈ lowerBounds t) : + a * b ∈ lowerBounds (s * t) := mul_mem_upperBounds_mul (M := Mᵒᵈ) ha hb + +@[to_additive] +lemma subset_lowerBounds_mul (s t : Set M) : lowerBounds s * lowerBounds t ⊆ lowerBounds (s * t) := + subset_upperBounds_mul (M := Mᵒᵈ) _ _ + +@[to_additive] +lemma BddAbove.mul (hs : BddAbove s) (ht : BddAbove t) : BddAbove (s * t) := + (Nonempty.mul hs ht).mono (subset_upperBounds_mul s t) + +@[to_additive] +lemma BddBelow.mul (hs : BddBelow s) (ht : BddBelow t) : BddBelow (s * t) := + (Nonempty.mul hs ht).mono (subset_lowerBounds_mul s t) + +@[to_additive] +lemma BddAbove.range_mul (hf : BddAbove (range f)) (hg : BddAbove (range g)) : + BddAbove (range fun i ↦ f i * g i) := + .range_comp (f := fun i ↦ (f i, g i)) (bddAbove_range_prod.2 ⟨hf, hg⟩) + (monotone_fst.mul' monotone_snd) + +@[to_additive] +lemma BddBelow.range_mul (hf : BddBelow (range f)) (hg : BddBelow (range g)) : + BddBelow (range fun i ↦ f i * g i) := BddAbove.range_mul (M := Mᵒᵈ) hf hg + +end Mul + +section InvNeg +variable [Group G] [Preorder G] [CovariantClass G G (· * ·) (· ≤ ·)] + [CovariantClass G G (swap (· * ·)) (· ≤ ·)] {s : Set G} {a : G} + +@[to_additive (attr := simp)] +theorem bddAbove_inv : BddAbove s⁻¹ ↔ BddBelow s := + (OrderIso.inv G).bddAbove_preimage + +@[to_additive (attr := simp)] +theorem bddBelow_inv : BddBelow s⁻¹ ↔ BddAbove s := + (OrderIso.inv G).bddBelow_preimage + +@[to_additive] +theorem BddAbove.inv (h : BddAbove s) : BddBelow s⁻¹ := + bddBelow_inv.2 h + +@[to_additive] +theorem BddBelow.inv (h : BddBelow s) : BddAbove s⁻¹ := + bddAbove_inv.2 h + +@[to_additive (attr := simp)] +theorem isLUB_inv : IsLUB s⁻¹ a ↔ IsGLB s a⁻¹ := + (OrderIso.inv G).isLUB_preimage + +@[to_additive] +theorem isLUB_inv' : IsLUB s⁻¹ a⁻¹ ↔ IsGLB s a := + (OrderIso.inv G).isLUB_preimage' + +@[to_additive] +theorem IsGLB.inv (h : IsGLB s a) : IsLUB s⁻¹ a⁻¹ := + isLUB_inv'.2 h + +@[to_additive (attr := simp)] +theorem isGLB_inv : IsGLB s⁻¹ a ↔ IsLUB s a⁻¹ := + (OrderIso.inv G).isGLB_preimage + +@[to_additive] +theorem isGLB_inv' : IsGLB s⁻¹ a⁻¹ ↔ IsLUB s a := + (OrderIso.inv G).isGLB_preimage' + +@[to_additive] +theorem IsLUB.inv (h : IsLUB s a) : IsGLB s⁻¹ a⁻¹ := + isGLB_inv'.2 h + +@[to_additive] +lemma BddBelow.range_inv {α : Type*} {f : α → G} (hf : BddBelow (range f)) : + BddAbove (range (fun x => (f x)⁻¹)) := + hf.range_comp (OrderIso.inv G).monotone + +@[to_additive] +lemma BddAbove.range_inv {α : Type*} {f : α → G} (hf : BddAbove (range f)) : + BddBelow (range (fun x => (f x)⁻¹)) := + BddBelow.range_inv (G := Gᵒᵈ) hf + +end InvNeg diff --git a/Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean b/Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean new file mode 100644 index 0000000000000..6f09d373cffd4 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2021 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Algebra.Order.Group.Pointwise.Bounds +import Mathlib.Order.ConditionallyCompleteLattice.Basic + +/-! +# Infima/suprema in ordered monoids and groups + +In this file we prove a few facts like “The infimum of `-s` is `-` the supremum of `s`”. + +## TODO + +`sSup (s • t) = sSup s • sSup t` and `sInf (s • t) = sInf s • sInf t` hold as well but +`CovariantClass` is currently not polymorphic enough to state it. +-/ + +open Function Set +open scoped Pointwise + +variable {ι G M : Type*} + +section ConditionallyCompleteLattice +variable [ConditionallyCompleteLattice M] + +section One +variable [One M] + +@[to_additive (attr := simp)] lemma csSup_one : sSup (1 : Set M) = 1 := csSup_singleton _ +@[to_additive (attr := simp)] lemma csInf_one : sInf (1 : Set M) = 1 := csInf_singleton _ + +end One + +section Group +variable [Group M] [CovariantClass M M (· * ·) (· ≤ ·)] [CovariantClass M M (swap (· * ·)) (· ≤ ·)] + {s t : Set M} + +@[to_additive] +lemma csSup_inv (hs₀ : s.Nonempty) (hs₁ : BddBelow s) : sSup s⁻¹ = (sInf s)⁻¹ := by + rw [← image_inv] + exact ((OrderIso.inv _).map_csInf' hs₀ hs₁).symm + +@[to_additive] +lemma csInf_inv (hs₀ : s.Nonempty) (hs₁ : BddAbove s) : sInf s⁻¹ = (sSup s)⁻¹ := by + rw [← image_inv] + exact ((OrderIso.inv _).map_csSup' hs₀ hs₁).symm + +@[to_additive] +lemma csSup_mul (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : + sSup (s * t) = sSup s * sSup t := + csSup_image2_eq_csSup_csSup (fun _ => (OrderIso.mulRight _).to_galoisConnection) + (fun _ => (OrderIso.mulLeft _).to_galoisConnection) hs₀ hs₁ ht₀ ht₁ + +@[to_additive] +lemma csInf_mul (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : + sInf (s * t) = sInf s * sInf t := + csInf_image2_eq_csInf_csInf (fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) + (fun _ => (OrderIso.mulLeft _).symm.to_galoisConnection) hs₀ hs₁ ht₀ ht₁ + +@[to_additive] +lemma csSup_div (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : + sSup (s / t) = sSup s / sInf t := by + rw [div_eq_mul_inv, csSup_mul hs₀ hs₁ ht₀.inv ht₁.inv, csSup_inv ht₀ ht₁, div_eq_mul_inv] + +@[to_additive] +lemma csInf_div (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : + sInf (s / t) = sInf s / sSup t := by + rw [div_eq_mul_inv, csInf_mul hs₀ hs₁ ht₀.inv ht₁.inv, csInf_inv ht₀ ht₁, div_eq_mul_inv] + +end Group +end ConditionallyCompleteLattice + +section CompleteLattice +variable [CompleteLattice M] + +section One +variable [One M] + +@[to_additive] lemma sSup_one : sSup (1 : Set M) = 1 := sSup_singleton +@[to_additive] lemma sInf_one : sInf (1 : Set M) = 1 := sInf_singleton + +end One + +section Group +variable [Group M] [CovariantClass M M (· * ·) (· ≤ ·)] [CovariantClass M M (swap (· * ·)) (· ≤ ·)] + (s t : Set M) + +@[to_additive] +lemma sSup_inv (s : Set M) : sSup s⁻¹ = (sInf s)⁻¹ := by + rw [← image_inv, sSup_image] + exact ((OrderIso.inv M).map_sInf _).symm + +@[to_additive] +lemma sInf_inv (s : Set M) : sInf s⁻¹ = (sSup s)⁻¹ := by + rw [← image_inv, sInf_image] + exact ((OrderIso.inv M).map_sSup _).symm + +@[to_additive] +lemma sSup_mul : sSup (s * t) = sSup s * sSup t := + (sSup_image2_eq_sSup_sSup fun _ => (OrderIso.mulRight _).to_galoisConnection) fun _ => + (OrderIso.mulLeft _).to_galoisConnection + +@[to_additive] +lemma sInf_mul : sInf (s * t) = sInf s * sInf t := + (sInf_image2_eq_sInf_sInf fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) fun _ => + (OrderIso.mulLeft _).symm.to_galoisConnection + +@[to_additive] +lemma sSup_div : sSup (s / t) = sSup s / sInf t := by simp_rw [div_eq_mul_inv, sSup_mul, sSup_inv] + +@[to_additive] +lemma sInf_div : sInf (s / t) = sInf s / sSup t := by simp_rw [div_eq_mul_inv, sInf_mul, sInf_inv] + +end Group +end CompleteLattice diff --git a/Mathlib/Algebra/Order/Pointwise.lean b/Mathlib/Algebra/Order/Pointwise.lean deleted file mode 100644 index 5a6d4539414dd..0000000000000 --- a/Mathlib/Algebra/Order/Pointwise.lean +++ /dev/null @@ -1,250 +0,0 @@ -/- -Copyright (c) 2021 Alex J. Best. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Alex J. Best, Yaël Dillies --/ -import Mathlib.Algebra.Bounds -import Mathlib.Algebra.Order.Field.Basic -- Porting note: `LinearOrderedField`, etc -import Mathlib.Algebra.SMulWithZero - -/-! -# Pointwise operations on ordered algebraic objects - -This file contains lemmas about the effect of pointwise operations on sets with an order structure. - -## TODO - -`sSup (s • t) = sSup s • sSup t` and `sInf (s • t) = sInf s • sInf t` hold as well but -`CovariantClass` is currently not polymorphic enough to state it. --/ - - -open Function Set - -open Pointwise - -variable {α : Type*} - --- Porting note: Swapped the place of `CompleteLattice` and `ConditionallyCompleteLattice` --- due to simpNF problem between `sSup_xx` `csSup_xx`. - -section CompleteLattice - -variable [CompleteLattice α] - -section One - -variable [One α] - -@[to_additive (attr := simp)] -theorem sSup_one : sSup (1 : Set α) = 1 := - sSup_singleton - -@[to_additive (attr := simp)] -theorem sInf_one : sInf (1 : Set α) = 1 := - sInf_singleton - -end One - -section Group - -variable [Group α] [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - (s t : Set α) - -@[to_additive] -theorem sSup_inv (s : Set α) : sSup s⁻¹ = (sInf s)⁻¹ := by - rw [← image_inv, sSup_image] - exact ((OrderIso.inv α).map_sInf _).symm - -@[to_additive] -theorem sInf_inv (s : Set α) : sInf s⁻¹ = (sSup s)⁻¹ := by - rw [← image_inv, sInf_image] - exact ((OrderIso.inv α).map_sSup _).symm - -@[to_additive] -theorem sSup_mul : sSup (s * t) = sSup s * sSup t := - (sSup_image2_eq_sSup_sSup fun _ => (OrderIso.mulRight _).to_galoisConnection) fun _ => - (OrderIso.mulLeft _).to_galoisConnection - -@[to_additive] -theorem sInf_mul : sInf (s * t) = sInf s * sInf t := - (sInf_image2_eq_sInf_sInf fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) fun _ => - (OrderIso.mulLeft _).symm.to_galoisConnection - -@[to_additive] -theorem sSup_div : sSup (s / t) = sSup s / sInf t := by simp_rw [div_eq_mul_inv, sSup_mul, sSup_inv] - -@[to_additive] -theorem sInf_div : sInf (s / t) = sInf s / sSup t := by simp_rw [div_eq_mul_inv, sInf_mul, sInf_inv] - -end Group - -end CompleteLattice - -section ConditionallyCompleteLattice - -variable [ConditionallyCompleteLattice α] - -section One - -variable [One α] - -@[to_additive (attr := simp)] -theorem csSup_one : sSup (1 : Set α) = 1 := - csSup_singleton _ - -@[to_additive (attr := simp)] -theorem csInf_one : sInf (1 : Set α) = 1 := - csInf_singleton _ - -end One - -section Group - -variable [Group α] [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - {s t : Set α} - -@[to_additive] -theorem csSup_inv (hs₀ : s.Nonempty) (hs₁ : BddBelow s) : sSup s⁻¹ = (sInf s)⁻¹ := by - rw [← image_inv] - exact ((OrderIso.inv α).map_csInf' hs₀ hs₁).symm - -@[to_additive] -theorem csInf_inv (hs₀ : s.Nonempty) (hs₁ : BddAbove s) : sInf s⁻¹ = (sSup s)⁻¹ := by - rw [← image_inv] - exact ((OrderIso.inv α).map_csSup' hs₀ hs₁).symm - -@[to_additive] -theorem csSup_mul (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : - sSup (s * t) = sSup s * sSup t := - csSup_image2_eq_csSup_csSup (fun _ => (OrderIso.mulRight _).to_galoisConnection) - (fun _ => (OrderIso.mulLeft _).to_galoisConnection) hs₀ hs₁ ht₀ ht₁ - -@[to_additive] -theorem csInf_mul (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : - sInf (s * t) = sInf s * sInf t := - csInf_image2_eq_csInf_csInf (fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) - (fun _ => (OrderIso.mulLeft _).symm.to_galoisConnection) hs₀ hs₁ ht₀ ht₁ - -@[to_additive] -theorem csSup_div (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : - sSup (s / t) = sSup s / sInf t := by - rw [div_eq_mul_inv, csSup_mul hs₀ hs₁ ht₀.inv ht₁.inv, csSup_inv ht₀ ht₁, div_eq_mul_inv] - -@[to_additive] -theorem csInf_div (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : - sInf (s / t) = sInf s / sSup t := by - rw [div_eq_mul_inv, csInf_mul hs₀ hs₁ ht₀.inv ht₁.inv, csInf_inv ht₀ ht₁, div_eq_mul_inv] - -end Group - -end ConditionallyCompleteLattice - -namespace LinearOrderedField - -variable {K : Type*} [LinearOrderedField K] {a b r : K} (hr : 0 < r) -include hr - -open Set - -theorem smul_Ioo : r • Ioo a b = Ioo (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioo] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_lt_mul_left hr).mpr a_h_left_left - · exact (mul_lt_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(lt_div_iff' hr).mpr a_left, (div_lt_iff' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Icc : r • Icc a b = Icc (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Icc] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_le_mul_left hr).mpr a_h_left_left - · exact (mul_le_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Ico : r • Ico a b = Ico (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ico] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_le_mul_left hr).mpr a_h_left_left - · exact (mul_lt_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_lt_iff' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Ioc : r • Ioc a b = Ioc (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioc] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_lt_mul_left hr).mpr a_h_left_left - · exact (mul_le_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(lt_div_iff' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Ioi : r • Ioi a = Ioi (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioi] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_lt_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (lt_div_iff' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -theorem smul_Iio : r • Iio a = Iio (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Iio] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_lt_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (div_lt_iff' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -theorem smul_Ici : r • Ici a = Ici (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioi] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_le_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (le_div_iff₀' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -theorem smul_Iic : r • Iic a = Iic (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Iio] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_le_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (div_le_iff₀' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -end LinearOrderedField diff --git a/Mathlib/Data/Real/Archimedean.lean b/Mathlib/Data/Real/Archimedean.lean index 320d601909bab..4df84980d7abb 100644 --- a/Mathlib/Data/Real/Archimedean.lean +++ b/Mathlib/Data/Real/Archimedean.lean @@ -3,8 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Floris van Doorn -/ -import Mathlib.Algebra.Bounds import Mathlib.Algebra.Order.Archimedean.Basic +import Mathlib.Algebra.Order.Group.Pointwise.Bounds import Mathlib.Data.Real.Basic import Mathlib.Order.Interval.Set.Disjoint diff --git a/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean b/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean index 9326504897129..76566b1a9cc1e 100644 --- a/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean +++ b/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.Order.Pointwise +import Mathlib.Algebra.Order.Field.Pointwise import Mathlib.Analysis.NormedSpace.SphereNormEquiv import Mathlib.Analysis.SpecialFunctions.Integrals import Mathlib.MeasureTheory.Constructions.Prod.Integral From 3488c1c235662ef6ff164df38d9cadd6a1e48888 Mon Sep 17 00:00:00 2001 From: Emily Riehl Date: Thu, 26 Sep 2024 00:42:52 +0000 Subject: [PATCH 159/170] feat(CategoryTheory): the internal hom with the monoidal unit is the identity (#17065) In a closed monoidal category, the internal hom defined by mapping out of the monoidal unit is naturally isomorphic to the identity. This specializes to an analogous result about exponentiating with the terminal object in a cartesian closed category. Co-authored-by: [Dagur Asgeirsson](https://github.com/dagurtomas) --- Mathlib/CategoryTheory/Closed/Cartesian.lean | 20 +++++++------------- Mathlib/CategoryTheory/Closed/Monoidal.lean | 4 ++++ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Mathlib/CategoryTheory/Closed/Cartesian.lean b/Mathlib/CategoryTheory/Closed/Cartesian.lean index c4ac634c52efb..e25efebbe63d0 100644 --- a/Mathlib/CategoryTheory/Closed/Cartesian.lean +++ b/Mathlib/CategoryTheory/Closed/Cartesian.lean @@ -226,21 +226,15 @@ end CartesianClosed open CartesianClosed -/-- Show that the exponential of the terminal object is isomorphic to itself, i.e. `X^1 ≅ X`. +/-- The exponential with the terminal object is naturally isomorphic to the identity. The typeclass +argument is explicit: any instance can be used.-/ +def expTerminalNatIso [Exponentiable (⊤_ C)] : 𝟭 C ≅ exp (⊤_ C) := + MonoidalClosed.unitNatIso (C := C) -The typeclass argument is explicit: any instance can be used. --/ +/-- The exponential of any object with the terminal object is isomorphic to itself, i.e. `X^1 ≅ X`. +The typeclass argument is explicit: any instance can be used.-/ def expTerminalIsoSelf [Exponentiable (⊤_ C)] : (⊤_ C) ⟹ X ≅ X := - Yoneda.ext ((⊤_ C) ⟹ X) X - (fun {Y} f => (Limits.prod.leftUnitor Y).inv ≫ CartesianClosed.uncurry f) - (fun {Y} f => CartesianClosed.curry ((Limits.prod.leftUnitor Y).hom ≫ f)) - (fun g => by - rw [curry_eq_iff, Iso.hom_inv_id_assoc]) - (fun g => by simp) - (fun f g => by - -- Porting note: `rw` is a bit brittle here, requiring the `dsimp` rule cancellation. - dsimp [-prod.leftUnitor_inv] - rw [uncurry_natural_left, prod.leftUnitor_inv_naturality_assoc f]) + (expTerminalNatIso.app X).symm /-- The internal element which points at the given morphism. -/ def internalizeHom (f : A ⟶ Y) : ⊤_ C ⟶ A ⟹ Y := diff --git a/Mathlib/CategoryTheory/Closed/Monoidal.lean b/Mathlib/CategoryTheory/Closed/Monoidal.lean index 8309157796ab1..43af4d461c0de 100644 --- a/Mathlib/CategoryTheory/Closed/Monoidal.lean +++ b/Mathlib/CategoryTheory/Closed/Monoidal.lean @@ -196,6 +196,10 @@ theorem curry_id_eq_coev : curry (𝟙 _) = (ihom.coev A).app X := by rw [curry_eq, (ihom A).map_id (A ⊗ _)] apply comp_id +/-- The internal hom out of the unit is naturally isomorphic to the identity functor.-/ +def unitNatIso [Closed (𝟙_ C)] : 𝟭 C ≅ ihom (𝟙_ C) := + conjugateIsoEquiv (Adjunction.id (C := C)) (ihom.adjunction (𝟙_ C)) + (leftUnitorNatIso C) section Pre variable {A B} From b272ab87df83543439885eb390ff5aa07a78777d Mon Sep 17 00:00:00 2001 From: Ira Fesefeldt Date: Thu, 26 Sep 2024 02:42:15 +0000 Subject: [PATCH 160/170] feat: monotonicity lemmas for OrdinalApprox (#15522) This PR adds two lemmas about monotonicity for `lfpApprox` and `gfpApprox` each. I found them helpful when working with the API. Co-authored-by: Ira Fesefeldt Co-authored-by: Ira Fesefeldt <9974411+PhoenixIra@users.noreply.github.com> --- .../Ordinal/FixedPointApproximants.lean | 58 +++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean index e7baa70d5b32b..ddec8ac7b3058 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean @@ -54,8 +54,6 @@ theorem not_injective_limitation_set : ¬ InjOn g (Iio (ord <| succ #α)) := by rw [mk_initialSeg_subtype, lift_lift, lift_le] at h exact not_le_of_lt (Order.lt_succ #α) h - - end Cardinal namespace OrdinalApprox @@ -76,7 +74,8 @@ termination_by a decreasing_by exact h theorem lfpApprox_monotone : Monotone (lfpApprox f x) := by - unfold Monotone; intros a b h; unfold lfpApprox + intros a b h + rw [lfpApprox, lfpApprox] refine sSup_le_sSup ?h apply sup_le_sup_right simp only [exists_prop, Set.le_eq_subset, Set.setOf_subset_setOf, forall_exists_index, and_imp, @@ -86,14 +85,14 @@ theorem lfpApprox_monotone : Monotone (lfpApprox f x) := by exact ⟨lt_of_lt_of_le h' h, rfl⟩ theorem le_lfpApprox {a : Ordinal} : x ≤ lfpApprox f x a := by - unfold lfpApprox + rw [lfpApprox] apply le_sSup simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, true_or] theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : lfpApprox f x (a+1) = f (lfpApprox f x a) := by apply le_antisymm - · conv => left; unfold lfpApprox + · conv => left; rw [lfpApprox] apply sSup_le simp only [Ordinal.add_one_eq_succ, lt_succ_iff, exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, forall_eq_or_imp, forall_exists_index, and_imp, @@ -104,7 +103,7 @@ theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : exact le_lfpApprox f x · intros a' h apply f.2; apply lfpApprox_monotone; exact h - · conv => right; unfold lfpApprox + · conv => right; rw [lfpApprox] apply le_sSup simp only [Ordinal.add_one_eq_succ, lt_succ_iff, exists_prop] rw [Set.mem_union] @@ -112,13 +111,46 @@ theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : simp only [Set.mem_setOf_eq] use a +theorem lfpApprox_mono_left : Monotone (lfpApprox : (α →o α) → _) := by + intro f g h x a + induction a using Ordinal.induction with + | h i ih => + rw [lfpApprox, lfpApprox] + apply sSup_le + simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, sSup_insert, + forall_eq_or_imp, le_sup_left, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, + true_and] + intro i' h_lt + apply le_sup_of_le_right + apply le_sSup_of_le + · use i' + · apply le_trans (h _) + simp only [OrderHom.toFun_eq_coe] + exact g.monotone (ih i' h_lt) + +theorem lfpApprox_mono_mid : Monotone (lfpApprox f) := by + intro x₁ x₂ h a + induction a using Ordinal.induction with + | h i ih => + rw [lfpApprox, lfpApprox] + apply sSup_le + simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, sSup_insert, + forall_eq_or_imp, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + constructor + · exact le_sup_of_le_left h + · intro i' h_i' + apply le_sup_of_le_right + apply le_sSup_of_le + · use i' + · exact f.monotone (ih i' h_i') + /-- The approximations of the least fixed point stabilize at a fixed point of `f` -/ theorem lfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : x ≤ f x) (h_ab : a ≤ b) (h : lfpApprox f x a ∈ fixedPoints f) : lfpApprox f x b = lfpApprox f x a := by rw [mem_fixedPoints_iff] at h induction b using Ordinal.induction with | h b IH => apply le_antisymm - · conv => left; unfold lfpApprox + · conv => left; rw [lfpApprox] apply sSup_le simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, forall_eq_or_imp, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] @@ -178,7 +210,7 @@ theorem lfpApprox_le_of_mem_fixedPoints {a : α} (h_a : a ∈ fixedPoints f) (h_le_init : x ≤ a) (i : Ordinal) : lfpApprox f x i ≤ a := by induction i using Ordinal.induction with | h i IH => - unfold lfpApprox + rw [lfpApprox] apply sSup_le simp only [exists_prop] intro y h_y @@ -187,8 +219,7 @@ theorem lfpApprox_le_of_mem_fixedPoints {a : α} | inl h_y => let ⟨j, h_j_lt, h_j⟩ := h_y rw [← h_j, ← h_a] - apply f.monotone' - exact IH j h_j_lt + exact f.monotone' (IH j h_j_lt) | inr h_y => rw [h_y] exact h_le_init @@ -234,6 +265,13 @@ theorem gfpApprox_add_one (h : f x ≤ x) (a : Ordinal) : gfpApprox f x (a+1) = f (gfpApprox f x a) := lfpApprox_add_one (OrderHom.dual f) x h a +theorem gfpApprox_mono_left : Monotone (gfpApprox : (α →o α) → _) := by + intro f g h + have : OrderHom.dual g ≤ OrderHom.dual f := h + exact lfpApprox_mono_left this + +theorem gfpApprox_mono_mid : Monotone (gfpApprox f) := + fun _ _ h => lfpApprox_mono_mid (OrderHom.dual f) h /-- The approximations of the greatest fixed point stabilize at a fixed point of `f` -/ theorem gfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : f x ≤ x) (h_ab : a ≤ b) From facf1f9c421d71ca630462709b7a4bd20638d451 Mon Sep 17 00:00:00 2001 From: Ahmad Alkhalawi Date: Thu, 26 Sep 2024 03:24:14 +0000 Subject: [PATCH 161/170] feat(LinearAlgebra/Matrix): Woodbury Identity (#16325) This adds the [Woodbury Identity](https://en.wikipedia.org/wiki/Woodbury_matrix_identity). [Zulip discussion](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Woodbury.20identity/near/462245284) Also corrects some bad deprecations introduced in #16590, which affected development of this PR. Co-authored-by: Mohanad Ahmad Co-authored-by: Eric Wieser --- Mathlib/Data/Matrix/Invertible.lean | 77 +++++++++++++++++-- .../Matrix/NonsingularInverse.lean | 18 +++++ 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/Mathlib/Data/Matrix/Invertible.lean b/Mathlib/Data/Matrix/Invertible.lean index 5b38bcb33b6e3..b68c2fb925d3d 100644 --- a/Mathlib/Data/Matrix/Invertible.lean +++ b/Mathlib/Data/Matrix/Invertible.lean @@ -1,9 +1,10 @@ /- Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Eric Wieser +Authors: Eric Wieser, Ahmad Alkhalawi -/ import Mathlib.Data.Matrix.Basic +import Mathlib.Tactic.Abel /-! # Extra lemmas about invertible matrices @@ -47,10 +48,12 @@ protected theorem invOf_mul_cancel_right (A : Matrix m n α) (B : Matrix n n α) protected theorem mul_invOf_cancel_right (A : Matrix m n α) (B : Matrix n n α) [Invertible B] : A * B * ⅟ B = A := by rw [Matrix.mul_assoc, mul_invOf_self, Matrix.mul_one] -@[deprecated (since := "2024-09-07")] alias invOf_mul_self_assoc := invOf_mul_cancel_left -@[deprecated (since := "2024-09-07")] alias mul_invOf_self_assoc := mul_invOf_cancel_left -@[deprecated (since := "2024-09-07")] alias mul_invOf_mul_self_cancel := invOf_mul_cancel_right -@[deprecated (since := "2024-09-07")] alias mul_mul_invOf_self_cancel := mul_invOf_cancel_right +@[deprecated (since := "2024-09-07")] alias invOf_mul_self_assoc := Matrix.invOf_mul_cancel_left +@[deprecated (since := "2024-09-07")] alias mul_invOf_self_assoc := Matrix.mul_invOf_cancel_left +@[deprecated (since := "2024-09-07")] +alias mul_invOf_mul_self_cancel := Matrix.invOf_mul_cancel_right +@[deprecated (since := "2024-09-07")] +alias mul_mul_invOf_self_cancel := Matrix.mul_invOf_cancel_right section ConjTranspose variable [StarRing α] (A : Matrix n n α) @@ -106,4 +109,68 @@ def transposeInvertibleEquivInvertible : Invertible Aᵀ ≃ Invertible A where end CommSemiring +section Ring + +section Woodbury + +variable [Fintype m] [DecidableEq m] [Ring α] + (A : Matrix n n α) (U : Matrix n m α) (C : Matrix m m α) (V : Matrix m n α) + [Invertible A] [Invertible C] [Invertible (⅟C + V * ⅟A * U)] + +-- No spaces around multiplication signs for better clarity +lemma add_mul_mul_invOf_mul_eq_one : + (A + U*C*V)*(⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A) = 1 := by + calc + (A + U*C*V)*(⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A) + _ = A*⅟A - A*⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A + U*C*V*⅟A - U*C*V*⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A := by + simp_rw [add_sub_assoc, add_mul, mul_sub, Matrix.mul_assoc] + _ = (1 + U*C*V*⅟A) - (U*⅟(⅟C + V*⅟A*U)*V*⅟A + U*C*V*⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A) := by + rw [mul_invOf_self, Matrix.one_mul] + abel + _ = 1 + U*C*V*⅟A - (U + U*C*V*⅟A*U)*⅟(⅟C + V*⅟A*U)*V*⅟A := by + rw [sub_right_inj, Matrix.add_mul, Matrix.add_mul, Matrix.add_mul] + _ = 1 + U*C*V*⅟A - U*C*(⅟C + V*⅟A*U)*⅟(⅟C + V*⅟A*U)*V*⅟A := by + congr + simp only [Matrix.mul_add, Matrix.mul_invOf_cancel_right, ← Matrix.mul_assoc] + _ = 1 := by + rw [Matrix.mul_invOf_cancel_right] + abel + +/-- Like `add_mul_mul_invOf_mul_eq_one`, but with multiplication reversed. -/ +lemma add_mul_mul_invOf_mul_eq_one' : + (⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A)*(A + U*C*V) = 1 := by + calc + (⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A)*(A + U*C*V) + _ = ⅟A*A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A*A + ⅟A*U*C*V - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A*U*C*V := by + simp_rw [add_sub_assoc, _root_.mul_add, _root_.sub_mul, Matrix.mul_assoc] + _ = (1 + ⅟A*U*C*V) - (⅟A*U*⅟(⅟C + V*⅟A*U)*V + ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A*U*C*V) := by + rw [invOf_mul_self, Matrix.invOf_mul_cancel_right] + abel + _ = 1 + ⅟A*U*C*V - ⅟A*U*⅟(⅟C + V*⅟A*U)*(V + V*⅟A*U*C*V) := by + rw [sub_right_inj, Matrix.mul_add] + simp_rw [Matrix.mul_assoc] + _ = 1 + ⅟A*U*C*V - ⅟A*U*⅟(⅟C + V*⅟A*U)*(⅟C + V*⅟A*U)*C*V := by + congr 1 + simp only [Matrix.mul_add, Matrix.add_mul, ← Matrix.mul_assoc, + Matrix.invOf_mul_cancel_right] + _ = 1 := by + rw [Matrix.invOf_mul_cancel_right] + abel + +/-- If matrices `A`, `C`, and `C⁻¹ + V * A⁻¹ * U` are invertible, then so is `A + U * C * V`-/ +def invertibleAddMulMul : Invertible (A + U*C*V) where + invOf := ⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A + invOf_mul_self := add_mul_mul_invOf_mul_eq_one' _ _ _ _ + mul_invOf_self := add_mul_mul_invOf_mul_eq_one _ _ _ _ + +/-- The **Woodbury Identity** (`⅟` version). -/ +theorem invOf_add_mul_mul [Invertible (A + U*C*V)] : + ⅟(A + U*C*V) = ⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A := by + letI := invertibleAddMulMul A U C V + convert (rfl : ⅟(A + U*C*V) = _) + +end Woodbury + +end Ring + end Matrix diff --git a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean index 0ba84d9e908d0..1482f940cd82d 100644 --- a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean +++ b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean @@ -607,6 +607,24 @@ theorem inv_diagonal (v : n → α) : (diagonal v)⁻¹ = diagonal (Ring.inverse end Diagonal +section Woodbury + +variable [Fintype m] [DecidableEq m] +variable (A : Matrix n n α) (U : Matrix n m α) (C : Matrix m m α) (V : Matrix m n α) + +/-- The **Woodbury Identity** (`⁻¹` version). -/ +theorem add_mul_mul_inv_eq_sub (hA : IsUnit A) (hC : IsUnit C) (hAC : IsUnit (C⁻¹ + V * A⁻¹ * U)) : + (A + U * C * V)⁻¹ = A⁻¹ - A⁻¹ * U * (C⁻¹ + V * A⁻¹ * U)⁻¹ * V * A⁻¹ := by + obtain ⟨_⟩ := hA.nonempty_invertible + obtain ⟨_⟩ := hC.nonempty_invertible + obtain ⟨iAC⟩ := hAC.nonempty_invertible + simp only [← invOf_eq_nonsing_inv] at iAC + letI := invertibleAddMulMul A U C V + simp only [← invOf_eq_nonsing_inv] + apply invOf_add_mul_mul + +end Woodbury + @[simp] theorem inv_inv_inv (A : Matrix n n α) : A⁻¹⁻¹⁻¹ = A⁻¹ := by by_cases h : IsUnit A.det From c52d5a96ad8b3b9e7809cef5dd9eb3e4de7055ed Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Thu, 26 Sep 2024 04:36:13 +0000 Subject: [PATCH 162/170] =?UTF-8?q?chore:=20fix=20type=20class=20assumptio?= =?UTF-8?q?ns=20for=20`NonUnitalStarAlgHom.map=5Fcfc=E2=82=99`=20(#17111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean index e5c7cea5ca34e..2895a56f474d3 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean @@ -428,9 +428,9 @@ open scoped ContinuousMapZero variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} [CommSemiring R] [Nontrivial R] [StarRing R] [MetricSpace R] [TopologicalSemiring R] [ContinuousStar R] [CommRing S] [Algebra R S] - [Ring A] [StarRing A] [TopologicalSpace A] [Module R A] + [NonUnitalRing A] [StarRing A] [TopologicalSpace A] [Module R A] [IsScalarTower R A A] [SMulCommClass R A A] - [Ring B] [StarRing B] [TopologicalSpace B] [Module R B] + [NonUnitalRing B] [StarRing B] [TopologicalSpace B] [Module R B] [IsScalarTower R B B] [SMulCommClass R B B] [Module S A] [Module S B] [IsScalarTower R S A] [IsScalarTower R S B] [NonUnitalContinuousFunctionalCalculus R p] [NonUnitalContinuousFunctionalCalculus R q] From 78a0b2f466ea466316f4a918ecdc26aab4a38cd9 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Thu, 26 Sep 2024 08:03:57 +0000 Subject: [PATCH 163/170] ci: add --nightlysha to create-adaptation-pr.sh (#17148) --- .github/workflows/nightly_detect_failure.yml | 2 +- scripts/create-adaptation-pr.sh | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/nightly_detect_failure.yml b/.github/workflows/nightly_detect_failure.yml index e1cfd9147086b..140f115408e95 100644 --- a/.github/workflows/nightly_detect_failure.yml +++ b/.github/workflows/nightly_detect_failure.yml @@ -210,7 +210,7 @@ jobs: bump_branch_suffix = bump_branch.replace('bump/', '') payload = f"🛠️: it looks like it's time to create a new bump/nightly-{current_version} branch from nightly-testing (specifically {sha}), and then PR that to {bump_branch}. " payload += "To do so semi-automatically, run the following script from mathlib root:\n\n" - payload += f"```bash\n./scripts/create-adaptation-pr.sh {bump_branch_suffix} {current_version}\n```\n" + payload += f"```bash\n./scripts/create-adaptation-pr.sh --bumpversion={bump_branch_suffix} --nightlydate={current_version} --nightlysha={sha}\n```\n" # Only post if the message is different # We compare the first 160 characters, since that includes the date and bump version if not messages or messages[0]['content'][:160] != payload[:160]: diff --git a/scripts/create-adaptation-pr.sh b/scripts/create-adaptation-pr.sh index 2e7d69f7916d8..4fb326cfac9d6 100755 --- a/scripts/create-adaptation-pr.sh +++ b/scripts/create-adaptation-pr.sh @@ -21,9 +21,10 @@ AUTO="no" usage() { echo "Usage: $0 " echo " or" - echo " $0 --bumpversion= --nightlydate= [--auto=]" + echo " $0 --bumpversion= --nightlydate= --nightlysha= [--auto=]" echo "BUMPVERSION: The upcoming release that we are targeting, e.g., 'v4.10.0'" echo "NIGHTLYDATE: The date of the nightly toolchain currently used on 'nightly-testing'" + echo "NIGHTLYSHA: The SHA of the nightly toolchain that we want to adapt to" echo "AUTO: Optional flag to specify automatic mode, default is 'no'" exit 1 } @@ -43,6 +44,10 @@ elif [ $# -ge 2 ]; then NIGHTLYDATE="${arg#*=}" shift ;; + --nightlysha=*) + NIGHTLYSHA="${arg#*=}" + shift + ;; --auto=*) AUTO="${arg#*=}" shift @@ -148,15 +153,14 @@ echo echo "### [auto] create a new branch 'bump/nightly-$NIGHTLYDATE' and merge the latest changes from 'origin/nightly-testing'" git checkout -b "bump/nightly-$NIGHTLYDATE" -git merge origin/nightly-testing || true # ignore error if there are conflicts +git merge $NIGHTLYSHA || true # ignore error if there are conflicts # Check if there are merge conflicts if git diff --name-only --diff-filter=U | grep -q .; then echo echo "### [auto] Conflict resolution" - echo "### Automatically choosing 'lean-toolchain' and 'lake-manifest.json' from the newer branch" - echo "### In this case, the newer branch is 'origin/nightly-testing'" - git checkout origin/nightly-testing -- lean-toolchain lake-manifest.json + echo "### Automatically choosing 'lean-toolchain' and 'lake-manifest.json' from 'nightly-testing'" + git checkout $NIGHTLYSHA -- lean-toolchain lake-manifest.json git add lean-toolchain lake-manifest.json fi @@ -172,6 +176,8 @@ if git diff --name-only --diff-filter=U | grep -q .; then echo echo "### [user] Conflict resolution" echo "We are merging the latest changes from 'origin/nightly-testing' into 'bump/nightly-$NIGHTLYDATE'" + echo "Specifically, we are merging the following version of 'origin/nightly-testing':" + echo "$NIGHTLYSHA" echo "There seem to be conflicts: please resolve them" echo "" echo " 1) Open `pwd` in a new terminal and run 'git status'" From 5d4532a2dda173281ee2def1295c77f1e5104d77 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Thu, 26 Sep 2024 10:19:33 +0000 Subject: [PATCH 164/170] chore: rename `AnalyticOn` to `AnalyticOnNhd`, and `AnalyticWithinOn` to `AnalyticOn` (#17146) For coherence with `ContinuousOn`, `DifferentiableOn` and so on. See Zulip https://leanprover.zulipchat.com/#narrow/stream/144837-PR-reviews/topic/Integrate.20analytic.20functions.20in.20the.20smooth.20hierarchy/near/471899268 This is 90% renaming all `AnalyticOn` to `AnalyticOnNhd` and then `AnalyticWithinOn` to `AnalyticOn`, and then adding deprecations. The 10% remaining is, when adding a deprecation `alias AnalyticOn.foo := AnalyticOnNhd.foo`, I noticed that `AnalyticOn.foo` would definitely make sense (with the new meaning of `AnalyticOn`), so I added the lemma with the new meaning instead of deprecating the old one. --- Archive/Hairer.lean | 2 +- Mathlib/Analysis/Analytic/Basic.lean | 100 +++++--- Mathlib/Analysis/Analytic/CPolynomial.lean | 39 ++- Mathlib/Analysis/Analytic/ChangeOrigin.lean | 21 +- Mathlib/Analysis/Analytic/Composition.lean | 30 ++- Mathlib/Analysis/Analytic/Constructions.lean | 236 +++++++++++------- Mathlib/Analysis/Analytic/IsolatedZeros.lean | 27 +- Mathlib/Analysis/Analytic/Linear.lean | 52 +++- Mathlib/Analysis/Analytic/Meromorphic.lean | 4 +- Mathlib/Analysis/Analytic/Polynomial.lean | 63 +++-- Mathlib/Analysis/Analytic/Uniqueness.lean | 22 +- Mathlib/Analysis/Analytic/Within.lean | 26 +- .../Analysis/Calculus/FDeriv/Analytic.lean | 54 ++-- Mathlib/Analysis/Complex/CauchyIntegral.lean | 31 ++- Mathlib/Analysis/Complex/OpenMapping.lean | 19 +- .../SpecialFunctions/Complex/Analytic.lean | 48 +++- .../Analysis/SpecialFunctions/Gamma/Beta.lean | 10 +- .../Geometry/Manifold/AnalyticManifold.lean | 42 ++-- Mathlib/NumberTheory/LSeries/Deriv.lean | 8 +- Mathlib/NumberTheory/LSeries/ZMod.lean | 22 +- docs/overview.yaml | 2 +- docs/undergrad.yaml | 2 +- scripts/no_lints_prime_decls.txt | 8 +- 23 files changed, 574 insertions(+), 294 deletions(-) diff --git a/Archive/Hairer.lean b/Archive/Hairer.lean index acd326c0b13bf..e9b91c32132a8 100644 --- a/Archive/Hairer.lean +++ b/Archive/Hairer.lean @@ -100,7 +100,7 @@ lemma inj_L : Injective (L ι) := fun g hg _h2g g_supp ↦ by simpa [mul_comm (g _), L] using congr($hp ⟨g, g_supp.trans ball_subset_closedBall, hg⟩) simp_rw [MvPolynomial.funext_iff, map_zero] - refine fun x ↦ AnalyticOn.eval_linearMap (EuclideanSpace.equiv ι ℝ).toLinearMap p + refine fun x ↦ AnalyticOnNhd.eval_linearMap (EuclideanSpace.equiv ι ℝ).toLinearMap p |>.eqOn_zero_of_preconnected_of_eventuallyEq_zero (preconnectedSpace_iff_univ.mp inferInstance) (z₀ := 0) trivial (Filter.mem_of_superset (Metric.ball_mem_nhds 0 zero_lt_one) ?_) trivial diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index 1abdcf481ef99..b2a03d4aec9d9 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -49,13 +49,13 @@ Additionally, let `f` be a function from `E` to `F`. * `HasFPowerSeriesAt f p x`: on some ball of center `x` with positive radius, holds `HasFPowerSeriesOnBall f p x r`. * `AnalyticAt 𝕜 f x`: there exists a power series `p` such that holds `HasFPowerSeriesAt f p x`. -* `AnalyticOn 𝕜 f s`: the function `f` is analytic at every point of `s`. +* `AnalyticOnNhd 𝕜 f s`: the function `f` is analytic at every point of `s`. -We also define versions of `HasFPowerSeriesOnBall`, `AnalyticAt`, and `AnalyticOn` restricted to a -set, similar to `ContinuousWithinAt`. See `Mathlib.Analysis.Analytic.Within` for basic properties. +We also define versions of `HasFPowerSeriesOnBall`, `AnalyticAt`, and `AnalyticOnNhd` restricted to +a set, similar to `ContinuousWithinAt`. See `Mathlib.Analysis.Analytic.Within` for basic properties. * `AnalyticWithinAt 𝕜 f s x` means a power series at `x` converges to `f` on `𝓝[s ∪ {x}] x`. -* `AnalyticWithinOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. +* `AnalyticOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. We develop the basic properties of these notions, notably: * If a function admits a power series, it is continuous (see @@ -384,14 +384,17 @@ def AnalyticWithinAt (f : E → F) (s : Set E) (x : E) : Prop := /-- Given a function `f : E → F`, we say that `f` is analytic on a set `s` if it is analytic around every point of `s`. -/ -def AnalyticOn (f : E → F) (s : Set E) := +def AnalyticOnNhd (f : E → F) (s : Set E) := ∀ x, x ∈ s → AnalyticAt 𝕜 f x /-- `f` is analytic within `s` if it is analytic within `s` at each point of `t`. Note that -this is weaker than `AnalyticOn 𝕜 f s`, as `f` is allowed to be arbitrary outside `s`. -/ -def AnalyticWithinOn (f : E → F) (s : Set E) : Prop := +this is weaker than `AnalyticOnNhd 𝕜 f s`, as `f` is allowed to be arbitrary outside `s`. -/ +def AnalyticOn (f : E → F) (s : Set E) : Prop := ∀ x ∈ s, AnalyticWithinAt 𝕜 f s x +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn := AnalyticOn + /-! ### `HasFPowerSeriesOnBall` and `HasFPowerSeriesWithinOnBall` -/ @@ -612,9 +615,12 @@ theorem HasFPowerSeriesAt.coeff_zero (hf : HasFPowerSeriesAt f pf x) (v : Fin 0 AnalyticWithinAt 𝕜 f univ x ↔ AnalyticAt 𝕜 f x := by simp [AnalyticWithinAt, AnalyticAt] -@[simp] lemma analyticWithinOn_univ {f : E → F} : - AnalyticWithinOn 𝕜 f univ ↔ AnalyticOn 𝕜 f univ := by - simp only [AnalyticWithinOn, analyticWithinAt_univ, AnalyticOn] +@[simp] lemma analyticOn_univ {f : E → F} : + AnalyticOn 𝕜 f univ ↔ AnalyticOnNhd 𝕜 f univ := by + simp only [AnalyticOn, analyticWithinAt_univ, AnalyticOnNhd] + +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_univ := analyticOn_univ lemma AnalyticWithinAt.mono (hf : AnalyticWithinAt 𝕜 f s x) (h : t ⊆ s) : AnalyticWithinAt 𝕜 f t x := by @@ -625,25 +631,37 @@ lemma AnalyticAt.analyticWithinAt (hf : AnalyticAt 𝕜 f x) : AnalyticWithinAt rw [← analyticWithinAt_univ] at hf apply hf.mono (subset_univ _) -lemma AnalyticOn.analyticWithinOn (hf : AnalyticOn 𝕜 f s) : AnalyticWithinOn 𝕜 f s := +lemma AnalyticOnNhd.analyticOn (hf : AnalyticOnNhd 𝕜 f s) : AnalyticOn 𝕜 f s := fun x hx ↦ (hf x hx).analyticWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.analyticWithinOn := AnalyticOnNhd.analyticOn + lemma AnalyticWithinAt.congr_of_eventuallyEq {f g : E → F} {s : Set E} {x : E} (hf : AnalyticWithinAt 𝕜 f s x) (hs : g =ᶠ[𝓝[s] x] f) (hx : g x = f x) : AnalyticWithinAt 𝕜 g s x := by rcases hf with ⟨p, hp⟩ exact ⟨p, hp.congr hs hx⟩ +lemma AnalyticWithinAt.congr_of_eventuallyEq_insert {f g : E → F} {s : Set E} {x : E} + (hf : AnalyticWithinAt 𝕜 f s x) (hs : g =ᶠ[𝓝[insert x s] x] f) : + AnalyticWithinAt 𝕜 g s x := by + apply hf.congr_of_eventuallyEq (nhdsWithin_mono x (subset_insert x s) hs) + apply mem_of_mem_nhdsWithin (mem_insert x s) hs + lemma AnalyticWithinAt.congr {f g : E → F} {s : Set E} {x : E} (hf : AnalyticWithinAt 𝕜 f s x) (hs : EqOn g f s) (hx : g x = f x) : AnalyticWithinAt 𝕜 g s x := hf.congr_of_eventuallyEq hs.eventuallyEq_nhdsWithin hx -lemma AnalyticWithinOn.congr {f g : E → F} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hs : EqOn g f s) : - AnalyticWithinOn 𝕜 g s := +lemma AnalyticOn.congr {f g : E → F} {s : Set E} + (hf : AnalyticOn 𝕜 f s) (hs : EqOn g f s) : + AnalyticOn 𝕜 g s := fun x m ↦ (hf x m).congr hs (hs m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.congr := AnalyticOn.congr + theorem AnalyticAt.congr (hf : AnalyticAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : AnalyticAt 𝕜 g x := let ⟨_, hpf⟩ := hf (hpf.congr hg).analyticAt @@ -651,28 +669,41 @@ theorem AnalyticAt.congr (hf : AnalyticAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : An theorem analyticAt_congr (h : f =ᶠ[𝓝 x] g) : AnalyticAt 𝕜 f x ↔ AnalyticAt 𝕜 g x := ⟨fun hf ↦ hf.congr h, fun hg ↦ hg.congr h.symm⟩ -theorem AnalyticOn.mono {s t : Set E} (hf : AnalyticOn 𝕜 f t) (hst : s ⊆ t) : AnalyticOn 𝕜 f s := +theorem AnalyticOnNhd.mono {s t : Set E} (hf : AnalyticOnNhd 𝕜 f t) (hst : s ⊆ t) : + AnalyticOnNhd 𝕜 f s := fun z hz => hf z (hst hz) -theorem AnalyticOn.congr' (hf : AnalyticOn 𝕜 f s) (hg : f =ᶠ[𝓝ˢ s] g) : - AnalyticOn 𝕜 g s := +theorem AnalyticOnNhd.congr' (hf : AnalyticOnNhd 𝕜 f s) (hg : f =ᶠ[𝓝ˢ s] g) : + AnalyticOnNhd 𝕜 g s := fun z hz => (hf z hz).congr (mem_nhdsSet_iff_forall.mp hg z hz) -theorem analyticOn_congr' (h : f =ᶠ[𝓝ˢ s] g) : AnalyticOn 𝕜 f s ↔ AnalyticOn 𝕜 g s := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.congr' := AnalyticOnNhd.congr' + +theorem analyticOnNhd_congr' (h : f =ᶠ[𝓝ˢ s] g) : AnalyticOnNhd 𝕜 f s ↔ AnalyticOnNhd 𝕜 g s := ⟨fun hf => hf.congr' h, fun hg => hg.congr' h.symm⟩ -theorem AnalyticOn.congr (hs : IsOpen s) (hf : AnalyticOn 𝕜 f s) (hg : s.EqOn f g) : - AnalyticOn 𝕜 g s := +@[deprecated (since := "2024-09-26")] +alias analyticOn_congr' := analyticOnNhd_congr' + +theorem AnalyticOnNhd.congr (hs : IsOpen s) (hf : AnalyticOnNhd 𝕜 f s) (hg : s.EqOn f g) : + AnalyticOnNhd 𝕜 g s := hf.congr' <| mem_nhdsSet_iff_forall.mpr (fun _ hz => eventuallyEq_iff_exists_mem.mpr ⟨s, hs.mem_nhds hz, hg⟩) -theorem analyticOn_congr (hs : IsOpen s) (h : s.EqOn f g) : AnalyticOn 𝕜 f s ↔ - AnalyticOn 𝕜 g s := ⟨fun hf => hf.congr hs h, fun hg => hg.congr hs h.symm⟩ +theorem analyticOnNhd_congr (hs : IsOpen s) (h : s.EqOn f g) : AnalyticOnNhd 𝕜 f s ↔ + AnalyticOnNhd 𝕜 g s := ⟨fun hf => hf.congr hs h, fun hg => hg.congr hs h.symm⟩ -lemma AnalyticWithinOn.mono {f : E → F} {s t : Set E} (h : AnalyticWithinOn 𝕜 f t) - (hs : s ⊆ t) : AnalyticWithinOn 𝕜 f s := +@[deprecated (since := "2024-09-26")] +alias analyticOn_congr := analyticOnNhd_congr + +lemma AnalyticOn.mono {f : E → F} {s t : Set E} (h : AnalyticOn 𝕜 f t) + (hs : s ⊆ t) : AnalyticOn 𝕜 f s := fun _ m ↦ (h _ (hs m)).mono hs +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.mono := AnalyticOn.mono + /-! ### Composition with linear maps -/ @@ -691,12 +722,16 @@ theorem ContinuousLinearMap.comp_hasFPowerSeriesOnBall (g : F →L[𝕜] G) /-- If a function `f` is analytic on a set `s` and `g` is linear, then `g ∘ f` is analytic on `s`. -/ -theorem ContinuousLinearMap.comp_analyticOn {s : Set E} (g : F →L[𝕜] G) (h : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (g ∘ f) s := by +theorem ContinuousLinearMap.comp_analyticOnNhd + {s : Set E} (g : F →L[𝕜] G) (h : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (g ∘ f) s := by rintro x hx rcases h x hx with ⟨p, r, hp⟩ exact ⟨g.compFormalMultilinearSeries p, r, g.comp_hasFPowerSeriesOnBall hp⟩ +@[deprecated (since := "2024-09-26")] +alias ContinuousLinearMap.comp_analyticOn := ContinuousLinearMap.comp_analyticOnNhd + /-! ### Relation between analytic function and the partial sums of its power series -/ @@ -1164,17 +1199,24 @@ protected theorem AnalyticAt.continuousAt (hf : AnalyticAt 𝕜 f x) : Continuou let ⟨_, hp⟩ := hf hp.continuousAt -protected theorem AnalyticOn.continuousOn {s : Set E} (hf : AnalyticOn 𝕜 f s) : ContinuousOn f s := +protected theorem AnalyticOnNhd.continuousOn {s : Set E} (hf : AnalyticOnNhd 𝕜 f s) : + ContinuousOn f s := fun x hx => (hf x hx).continuousAt.continuousWithinAt -protected lemma AnalyticWithinOn.continuousOn {f : E → F} {s : Set E} (h : AnalyticWithinOn 𝕜 f s) : +protected lemma AnalyticOn.continuousOn {f : E → F} {s : Set E} (h : AnalyticOn 𝕜 f s) : ContinuousOn f s := fun x m ↦ (h x m).continuousWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.continuousOn := AnalyticOn.continuousOn + /-- Analytic everywhere implies continuous -/ -theorem AnalyticOn.continuous {f : E → F} (fa : AnalyticOn 𝕜 f univ) : Continuous f := by +theorem AnalyticOnNhd.continuous {f : E → F} (fa : AnalyticOnNhd 𝕜 f univ) : Continuous f := by rw [continuous_iff_continuousOn_univ]; exact fa.continuousOn +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.continuous := AnalyticOnNhd.continuous + /-- In a complete space, the sum of a converging power series `p` admits `p` as a power series. This is not totally obvious as we need to check the convergence of the series. -/ protected theorem FormalMultilinearSeries.hasFPowerSeriesOnBall [CompleteSpace F] diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean index bda50d02ecbfb..611b6258978a1 100644 --- a/Mathlib/Analysis/Analytic/CPolynomial.lean +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -29,7 +29,7 @@ for `n : ℕ`, and let `f` be a function from `E` to `F`. We develop the basic properties of these notions, notably: * If a function is continuously polynomial, then it is analytic, see `HasFiniteFPowerSeriesOnBall.hasFPowerSeriesOnBall`, `HasFiniteFPowerSeriesAt.hasFPowerSeriesAt`, - `CPolynomialAt.analyticAt` and `CPolynomialOn.analyticOn`. + `CPolynomialAt.analyticAt` and `CPolynomialOn.analyticOnNhd`. * The sum of a finite formal power series with positive radius is well defined on the whole space, see `FormalMultilinearSeries.hasFiniteFPowerSeriesOnBall_of_finite`. * If a function admits a finite power series in a ball, then it is continuously polynomial at @@ -116,9 +116,16 @@ theorem CPolynomialAt.analyticAt (hf : CPolynomialAt 𝕜 f x) : AnalyticAt 𝕜 let ⟨p, _, hp⟩ := hf ⟨p, hp.toHasFPowerSeriesAt⟩ -theorem CPolynomialOn.analyticOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOn 𝕜 f s := +theorem CPolynomialAt.analyticWithinAt {s : Set E} (hf : CPolynomialAt 𝕜 f x) : + AnalyticWithinAt 𝕜 f s x := + hf.analyticAt.analyticWithinAt + +theorem CPolynomialOn.analyticOnNhd {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOnNhd 𝕜 f s := fun x hx ↦ (hf x hx).analyticAt +theorem CPolynomialOn.analyticOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOn 𝕜 f s := + hf.analyticOnNhd.analyticOn + theorem HasFiniteFPowerSeriesOnBall.congr (hf : HasFiniteFPowerSeriesOnBall f p x n r) (hg : EqOn f g (EMetric.ball x r)) : HasFiniteFPowerSeriesOnBall g p x n r := ⟨hf.1.congr hg, hf.finite⟩ @@ -335,7 +342,7 @@ protected theorem CPolynomialAt.continuousAt (hf : CPolynomialAt 𝕜 f x) : Con protected theorem CPolynomialOn.continuousOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : ContinuousOn f s := - hf.analyticOn.continuousOn + hf.analyticOnNhd.continuousOn /-- Continuously polynomial everywhere implies continuous -/ theorem CPolynomialOn.continuous {f : E → F} (fa : CPolynomialOn 𝕜 f univ) : Continuous f := by @@ -571,10 +578,12 @@ lemma cpolynomialAt : CPolynomialAt 𝕜 f x := lemma cpolyomialOn : CPolynomialOn 𝕜 f s := fun _ _ ↦ f.cpolynomialAt -lemma analyticOn : AnalyticOn 𝕜 f s := f.cpolyomialOn.analyticOn +lemma analyticOnNhd : AnalyticOnNhd 𝕜 f s := f.cpolyomialOn.analyticOnNhd + +lemma analyticOn : AnalyticOn 𝕜 f s := f.analyticOnNhd.analyticOn -lemma analyticWithinOn : AnalyticWithinOn 𝕜 f s := - f.analyticOn.analyticWithinOn +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := analyticOn lemma analyticAt : AnalyticAt 𝕜 f x := f.cpolynomialAt.analyticAt @@ -624,12 +633,16 @@ lemma cpolyomialOn_uncurry_of_multilinear : CPolynomialOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := fun _ _ ↦ f.cpolynomialAt_uncurry_of_multilinear -lemma analyticOn_uncurry_of_multilinear : AnalyticOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := - f.cpolyomialOn_uncurry_of_multilinear.analyticOn +lemma analyticOnNhd_uncurry_of_multilinear : + AnalyticOnNhd 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := + f.cpolyomialOn_uncurry_of_multilinear.analyticOnNhd + +lemma analyticOn_uncurry_of_multilinear : + AnalyticOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := + f.analyticOnNhd_uncurry_of_multilinear.analyticOn -lemma analyticWithinOn_uncurry_of_multilinear : - AnalyticWithinOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := - f.analyticOn_uncurry_of_multilinear.analyticWithinOn +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_uncurry_of_multilinear := analyticOn_uncurry_of_multilinear lemma analyticAt_uncurry_of_multilinear : AnalyticAt 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) x := f.cpolynomialAt_uncurry_of_multilinear.analyticAt @@ -640,11 +653,11 @@ lemma analyticWithinAt_uncurry_of_multilinear : lemma continuousOn_uncurry_of_multilinear : ContinuousOn (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := - f.analyticOn_uncurry_of_multilinear.continuousOn + f.analyticOnNhd_uncurry_of_multilinear.continuousOn lemma continuous_uncurry_of_multilinear : Continuous (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) := - f.analyticOn_uncurry_of_multilinear.continuous + f.analyticOnNhd_uncurry_of_multilinear.continuous lemma continuousAt_uncurry_of_multilinear : ContinuousAt (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) x := diff --git a/Mathlib/Analysis/Analytic/ChangeOrigin.lean b/Mathlib/Analysis/Analytic/ChangeOrigin.lean index de0ca613e74d3..ea293a3262884 100644 --- a/Mathlib/Analysis/Analytic/ChangeOrigin.lean +++ b/Mathlib/Analysis/Analytic/ChangeOrigin.lean @@ -318,10 +318,13 @@ theorem HasFPowerSeriesOnBall.analyticAt_of_mem (hf : HasFPowerSeriesOnBall f p rw [add_sub_cancel] at this exact this.analyticAt -theorem HasFPowerSeriesOnBall.analyticOn (hf : HasFPowerSeriesOnBall f p x r) : - AnalyticOn 𝕜 f (EMetric.ball x r) := +theorem HasFPowerSeriesOnBall.analyticOnNhd (hf : HasFPowerSeriesOnBall f p x r) : + AnalyticOnNhd 𝕜 f (EMetric.ball x r) := fun _y hy => hf.analyticAt_of_mem hy +@[deprecated (since := "2024-09-26")] +alias HasFPowerSeriesOnBall.analyticOn := HasFPowerSeriesOnBall.analyticOnNhd + variable (𝕜 f) in /-- For any function `f` from a normed vector space to a Banach space, the set of points `x` such that `f` is analytic at `x` is open. -/ @@ -334,13 +337,19 @@ theorem AnalyticAt.eventually_analyticAt (h : AnalyticAt 𝕜 f x) : ∀ᶠ y in 𝓝 x, AnalyticAt 𝕜 f y := (isOpen_analyticAt 𝕜 f).mem_nhds h -theorem AnalyticAt.exists_mem_nhds_analyticOn (h : AnalyticAt 𝕜 f x) : - ∃ s ∈ 𝓝 x, AnalyticOn 𝕜 f s := +theorem AnalyticAt.exists_mem_nhds_analyticOnNhd (h : AnalyticAt 𝕜 f x) : + ∃ s ∈ 𝓝 x, AnalyticOnNhd 𝕜 f s := h.eventually_analyticAt.exists_mem +@[deprecated (since := "2024-09-26")] +alias AnalyticAt.exists_mem_nhds_analyticOn := AnalyticAt.exists_mem_nhds_analyticOnNhd + /-- If we're analytic at a point, we're analytic in a nonempty ball -/ -theorem AnalyticAt.exists_ball_analyticOn (h : AnalyticAt 𝕜 f x) : - ∃ r : ℝ, 0 < r ∧ AnalyticOn 𝕜 f (Metric.ball x r) := +theorem AnalyticAt.exists_ball_analyticOnNhd (h : AnalyticAt 𝕜 f x) : + ∃ r : ℝ, 0 < r ∧ AnalyticOnNhd 𝕜 f (Metric.ball x r) := Metric.isOpen_iff.mp (isOpen_analyticAt _ _) _ h +@[deprecated (since := "2024-09-26")] +alias AnalyticAt.exists_ball_analyticOn := AnalyticAt.exists_ball_analyticOnNhd + end diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index a6ee6bbde78ed..8b33f213f757e 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -830,11 +830,14 @@ theorem AnalyticWithinAt.comp_of_eq {g : F → G} {f : E → F} {y : F} {x : E} rw [← hy] at hg exact hg.comp hf h -lemma AnalyticWithinOn.comp {f : F → G} {g : E → F} {s : Set F} - {t : Set E} (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g t) (h : Set.MapsTo g t s) : - AnalyticWithinOn 𝕜 (f ∘ g) t := +lemma AnalyticOn.comp {f : F → G} {g : E → F} {s : Set F} + {t : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g t) (h : Set.MapsTo g t s) : + AnalyticOn 𝕜 (f ∘ g) t := fun x m ↦ (hf _ (h m)).comp (hg x m) h +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.comp := AnalyticOn.comp + /-- If two functions `g` and `f` are analytic respectively at `f x` and `x`, then `g ∘ f` is analytic at `x`. -/ theorem AnalyticAt.comp {g : F → G} {f : E → F} {x : E} (hg : AnalyticAt 𝕜 g (f x)) @@ -862,19 +865,26 @@ theorem AnalyticAt.comp_analyticWithinAt_of_eq {g : F → G} {f : E → F} {x : /-- If two functions `g` and `f` are analytic respectively on `s.image f` and `s`, then `g ∘ f` is analytic on `s`. -/ -theorem AnalyticOn.comp' {s : Set E} {g : F → G} {f : E → F} (hg : AnalyticOn 𝕜 g (s.image f)) - (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (g ∘ f) s := +theorem AnalyticOnNhd.comp' {s : Set E} {g : F → G} {f : E → F} (hg : AnalyticOnNhd 𝕜 g (s.image f)) + (hf : AnalyticOnNhd 𝕜 f s) : AnalyticOnNhd 𝕜 (g ∘ f) s := fun z hz => (hg (f z) (Set.mem_image_of_mem f hz)).comp (hf z hz) -theorem AnalyticOn.comp {s : Set E} {t : Set F} {g : F → G} {f : E → F} (hg : AnalyticOn 𝕜 g t) - (hf : AnalyticOn 𝕜 f s) (st : Set.MapsTo f s t) : AnalyticOn 𝕜 (g ∘ f) s := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.comp' := AnalyticOnNhd.comp' + +theorem AnalyticOnNhd.comp {s : Set E} {t : Set F} {g : F → G} {f : E → F} + (hg : AnalyticOnNhd 𝕜 g t) (hf : AnalyticOnNhd 𝕜 f s) (st : Set.MapsTo f s t) : + AnalyticOnNhd 𝕜 (g ∘ f) s := comp' (mono hg (Set.mapsTo'.mp st)) hf -lemma AnalyticOn.comp_analyticWithinOn {f : F → G} {g : E → F} {s : Set F} - {t : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g t) (h : Set.MapsTo g t s) : - AnalyticWithinOn 𝕜 (f ∘ g) t := +lemma AnalyticOnNhd.comp_analyticOn {f : F → G} {g : E → F} {s : Set F} + {t : Set E} (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOn 𝕜 g t) (h : Set.MapsTo g t s) : + AnalyticOn 𝕜 (f ∘ g) t := fun x m ↦ (hf _ (h m)).comp_analyticWithinAt (hg x m) +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.comp_analyticWithinOn := AnalyticOnNhd.comp_analyticOn + /-! ### Associativity of the composition of formal multilinear series diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index 5b268c5b5d826..7ef5b6a75773b 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -48,14 +48,17 @@ theorem hasFPowerSeriesAt_const {c : F} {e : E} : theorem analyticAt_const {v : F} {x : E} : AnalyticAt 𝕜 (fun _ => v) x := ⟨constFormalMultilinearSeries 𝕜 E v, hasFPowerSeriesAt_const⟩ -theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := +theorem analyticOnNhd_const {v : F} {s : Set E} : AnalyticOnNhd 𝕜 (fun _ => v) s := fun _ _ => analyticAt_const theorem analyticWithinAt_const {v : F} {s : Set E} {x : E} : AnalyticWithinAt 𝕜 (fun _ => v) s x := analyticAt_const.analyticWithinAt -theorem analyticWithinOn_const {v : F} {s : Set E} : AnalyticWithinOn 𝕜 (fun _ => v) s := - analyticOn_const.analyticWithinOn +theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := + analyticOnNhd_const.analyticOn + +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_const := analyticOn_const /-! ### Addition, negation, subtraction @@ -159,28 +162,37 @@ theorem AnalyticAt.sub (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : AnalyticAt 𝕜 (f - g) x := by simpa only [sub_eq_add_neg] using hf.add hg.neg -theorem AnalyticWithinOn.add (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (f + g) s := - fun z hz => (hf z hz).add (hg z hz) - theorem AnalyticOn.add (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : AnalyticOn 𝕜 (f + g) s := fun z hz => (hf z hz).add (hg z hz) -theorem AnalyticWithinOn.neg (hf : AnalyticWithinOn 𝕜 f s) : AnalyticWithinOn 𝕜 (-f) s := - fun z hz ↦ (hf z hz).neg +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.add := AnalyticOn.add + +theorem AnalyticOnNhd.add (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (f + g) s := + fun z hz => (hf z hz).add (hg z hz) theorem AnalyticOn.neg (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (-f) s := fun z hz ↦ (hf z hz).neg -theorem AnalyticWithinOn.sub (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (f - g) s := - fun z hz => (hf z hz).sub (hg z hz) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.neg := AnalyticOn.neg + +theorem AnalyticOnNhd.neg (hf : AnalyticOnNhd 𝕜 f s) : AnalyticOnNhd 𝕜 (-f) s := + fun z hz ↦ (hf z hz).neg theorem AnalyticOn.sub (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : AnalyticOn 𝕜 (f - g) s := fun z hz => (hf z hz).sub (hg z hz) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.sub := AnalyticOn.sub + +theorem AnalyticOnNhd.sub (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (f - g) s := + fun z hz => (hf z hz).sub (hg z hz) + end /-! @@ -270,17 +282,20 @@ lemma AnalyticAt.prod {e : E} {f : E → F} {g : E → G} exact ⟨_, hf.prod hg⟩ /-- The Cartesian product of analytic functions within a set is analytic. -/ -lemma AnalyticWithinOn.prod {f : E → F} {g : E → G} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (fun x ↦ (f x, g x)) s := - fun x hx ↦ (hf x hx).prod (hg x hx) - -/-- The Cartesian product of analytic functions is analytic. -/ lemma AnalyticOn.prod {f : E → F} {g : E → G} {s : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : AnalyticOn 𝕜 (fun x ↦ (f x, g x)) s := fun x hx ↦ (hf x hx).prod (hg x hx) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.prod := AnalyticOn.prod + +/-- The Cartesian product of analytic functions is analytic. -/ +lemma AnalyticOnNhd.prod {f : E → F} {g : E → G} {s : Set E} + (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (fun x ↦ (f x, g x)) s := + fun x hx ↦ (hf x hx).prod (hg x hx) + /-- `AnalyticAt.comp` for functions on product spaces -/ theorem AnalyticAt.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {x : E} (ha : AnalyticAt 𝕜 h (f x, g x)) (fa : AnalyticAt 𝕜 f x) @@ -304,20 +319,23 @@ theorem AnalyticAt.comp₂_analyticWithinAt AnalyticWithinAt 𝕜 (fun x ↦ h (f x, g x)) s x := AnalyticAt.comp_analyticWithinAt ha (fa.prod ga) -/-- `AnalyticOn.comp` for functions on product spaces -/ -theorem AnalyticOn.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} {t : Set E} - (ha : AnalyticOn 𝕜 h s) (fa : AnalyticOn 𝕜 f t) (ga : AnalyticOn 𝕜 g t) - (m : ∀ x, x ∈ t → (f x, g x) ∈ s) : AnalyticOn 𝕜 (fun x ↦ h (f x, g x)) t := +/-- `AnalyticOnNhd.comp` for functions on product spaces -/ +theorem AnalyticOnNhd.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} {t : Set E} + (ha : AnalyticOnNhd 𝕜 h s) (fa : AnalyticOnNhd 𝕜 f t) (ga : AnalyticOnNhd 𝕜 g t) + (m : ∀ x, x ∈ t → (f x, g x) ∈ s) : AnalyticOnNhd 𝕜 (fun x ↦ h (f x, g x)) t := fun _ xt ↦ (ha _ (m _ xt)).comp₂ (fa _ xt) (ga _ xt) -/-- `AnalyticWithinOn.comp` for functions on product spaces -/ -theorem AnalyticWithinOn.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} +/-- `AnalyticOn.comp` for functions on product spaces -/ +theorem AnalyticOn.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} {t : Set E} - (ha : AnalyticWithinOn 𝕜 h s) (fa : AnalyticWithinOn 𝕜 f t) - (ga : AnalyticWithinOn 𝕜 g t) (m : Set.MapsTo (fun y ↦ (f y, g y)) t s) : - AnalyticWithinOn 𝕜 (fun x ↦ h (f x, g x)) t := + (ha : AnalyticOn 𝕜 h s) (fa : AnalyticOn 𝕜 f t) + (ga : AnalyticOn 𝕜 g t) (m : Set.MapsTo (fun y ↦ (f y, g y)) t s) : + AnalyticOn 𝕜 (fun x ↦ h (f x, g x)) t := fun x hx ↦ (ha _ (m hx)).comp₂ (fa x hx) (ga x hx) m +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.comp₂ := AnalyticOn.comp₂ + /-- Analytic functions on products are analytic in the first coordinate -/ theorem AnalyticAt.curry_left {f : E × F → G} {p : E × F} (fa : AnalyticAt 𝕜 f p) : AnalyticAt 𝕜 (fun x ↦ f (x, p.2)) p.1 := @@ -341,27 +359,41 @@ theorem AnalyticWithinAt.curry_right AnalyticWithinAt.comp₂ fa analyticWithinAt_const analyticWithinAt_id (fun _ hx ↦ hx) /-- Analytic functions on products are analytic in the first coordinate -/ -theorem AnalyticOn.curry_left {f : E × F → G} {s : Set (E × F)} {y : F} (fa : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := +theorem AnalyticOnNhd.curry_left {f : E × F → G} {s : Set (E × F)} {y : F} + (fa : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := fun x m ↦ (fa (x, y) m).curry_left -alias AnalyticOn.along_fst := AnalyticOn.curry_left +alias AnalyticOnNhd.along_fst := AnalyticOnNhd.curry_left + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.along_fst := AnalyticOnNhd.curry_left -theorem AnalyticWithinOn.curry_left - {f : E × F → G} {s : Set (E × F)} {y : F} (fa : AnalyticWithinOn 𝕜 f s) : - AnalyticWithinOn 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := +theorem AnalyticOn.curry_left + {f : E × F → G} {s : Set (E × F)} {y : F} (fa : AnalyticOn 𝕜 f s) : + AnalyticOn 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := fun x m ↦ (fa (x, y) m).curry_left +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.curry_left := AnalyticOn.curry_left + /-- Analytic functions on products are analytic in the second coordinate -/ -theorem AnalyticOn.curry_right {f : E × F → G} {x : E} {s : Set (E × F)} (fa : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := +theorem AnalyticOnNhd.curry_right {f : E × F → G} {x : E} {s : Set (E × F)} + (fa : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := fun y m ↦ (fa (x, y) m).curry_right -alias AnalyticOn.along_snd := AnalyticOn.curry_right +alias AnalyticOnNhd.along_snd := AnalyticOnNhd.curry_right -theorem AnalyticWithinOn.curry_right - {f : E × F → G} {x : E} {s : Set (E × F)} (fa : AnalyticWithinOn 𝕜 f s) : - AnalyticWithinOn 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.along_snd := AnalyticOnNhd.curry_right + +theorem AnalyticOn.curry_right + {f : E × F → G} {x : E} {s : Set (E × F)} (fa : AnalyticOn 𝕜 f s) : + AnalyticOn 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := fun y m ↦ (fa (x, y) m).curry_right +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.curry_right := AnalyticOn.curry_right + /-! ### Analyticity in Pi spaces @@ -491,20 +523,26 @@ lemma analyticAt_pi_iff : simp_rw [← analyticWithinAt_univ] exact analyticWithinAt_pi_iff -lemma AnalyticWithinOn.pi (hf : ∀ i, AnalyticWithinOn 𝕜 (f i) s) : - AnalyticWithinOn 𝕜 (fun x ↦ (f · x)) s := +lemma AnalyticOn.pi (hf : ∀ i, AnalyticOn 𝕜 (f i) s) : + AnalyticOn 𝕜 (fun x ↦ (f · x)) s := fun x hx ↦ AnalyticWithinAt.pi (fun i ↦ hf i x hx) -lemma analyticWithinOn_pi_iff : - AnalyticWithinOn 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticWithinOn 𝕜 (f i) s := +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.pi := AnalyticOn.pi + +lemma analyticOn_pi_iff : + AnalyticOn 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticOn 𝕜 (f i) s := ⟨fun h i x hx ↦ analyticWithinAt_pi_iff.1 (h x hx) i, fun h ↦ .pi h⟩ -lemma AnalyticOn.pi (hf : ∀ i, AnalyticOn 𝕜 (f i) s) : - AnalyticOn 𝕜 (fun x ↦ (f · x)) s := +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_pi_iff := analyticOn_pi_iff + +lemma AnalyticOnNhd.pi (hf : ∀ i, AnalyticOnNhd 𝕜 (f i) s) : + AnalyticOnNhd 𝕜 (fun x ↦ (f · x)) s := fun x hx ↦ AnalyticAt.pi (fun i ↦ hf i x hx) -lemma analyticOn_pi_iff : - AnalyticOn 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticOn 𝕜 (f i) s := +lemma analyticOnNhd_pi_iff : + AnalyticOnNhd 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticOnNhd 𝕜 (f i) s := ⟨fun h i x hx ↦ analyticAt_pi_iff.1 (h x hx) i, fun h ↦ .pi h⟩ end @@ -540,16 +578,19 @@ lemma AnalyticAt.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E (analyticAt_smul _).comp₂ hf hg /-- Scalar multiplication of one analytic function by another. -/ -lemma AnalyticWithinOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] +lemma AnalyticOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (fun x ↦ f x • g x) s := + (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : + AnalyticOn 𝕜 (fun x ↦ f x • g x) s := fun _ m ↦ (hf _ m).smul (hg _ m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.smul := AnalyticOn.smul + /-- Scalar multiplication of one analytic function by another. -/ -lemma AnalyticOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} - (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : - AnalyticOn 𝕜 (fun x ↦ f x • g x) s := +lemma AnalyticOnNhd.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} + (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (fun x ↦ f x • g x) s := fun _ m ↦ (hf _ m).smul (hg _ m) /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ @@ -564,14 +605,18 @@ lemma AnalyticAt.mul {f g : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (hg : An (analyticAt_mul _).comp₂ hf hg /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ -lemma AnalyticWithinOn.mul {f g : E → A} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (fun x ↦ f x * g x) s := +lemma AnalyticOn.mul {f g : E → A} {s : Set E} + (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : + AnalyticOn 𝕜 (fun x ↦ f x * g x) s := fun _ m ↦ (hf _ m).mul (hg _ m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.mul := AnalyticOn.mul + /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ -lemma AnalyticOn.mul {f g : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : - AnalyticOn 𝕜 (fun x ↦ f x * g x) s := +lemma AnalyticOnNhd.mul {f g : E → A} {s : Set E} + (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (fun x ↦ f x * g x) s := fun _ m ↦ (hf _ m).mul (hg _ m) /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ @@ -592,13 +637,16 @@ lemma AnalyticAt.pow {f : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (n : ℕ) exact hf.pow n /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ -lemma AnalyticWithinOn.pow {f : E → A} {s : Set E} (hf : AnalyticWithinOn 𝕜 f s) (n : ℕ) : - AnalyticWithinOn 𝕜 (fun x ↦ f x ^ n) s := +lemma AnalyticOn.pow {f : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (n : ℕ) : + AnalyticOn 𝕜 (fun x ↦ f x ^ n) s := fun _ m ↦ (hf _ m).pow n +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.pow := AnalyticOn.pow + /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ -lemma AnalyticOn.pow {f : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (n : ℕ) : - AnalyticOn 𝕜 (fun x ↦ f x ^ n) s := +lemma AnalyticOnNhd.pow {f : E → A} {s : Set E} (hf : AnalyticOnNhd 𝕜 f s) (n : ℕ) : + AnalyticOnNhd 𝕜 (fun x ↦ f x ^ n) s := fun _ m ↦ (hf _ m).pow n section Geometric @@ -726,9 +774,12 @@ lemma analyticAt_inv {z : 𝕝} (hz : z ≠ 0) : AnalyticAt 𝕜 Inv.inv z := by exact Ring.inverse_eq_inv'.symm /-- `x⁻¹` is analytic away from zero -/ -lemma analyticOn_inv : AnalyticOn 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := by +lemma analyticOnNhd_inv : AnalyticOnNhd 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := by intro z m; exact analyticAt_inv m +lemma analyticOn_inv : AnalyticOn 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := + analyticOnNhd_inv.analyticOn + /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ theorem AnalyticWithinAt.inv {f : E → 𝕝} {x : E} {s : Set E} (fa : AnalyticWithinAt 𝕜 f s x) (f0 : f x ≠ 0) : @@ -741,14 +792,18 @@ theorem AnalyticAt.inv {f : E → 𝕝} {x : E} (fa : AnalyticAt 𝕜 f x) (f0 : (analyticAt_inv f0).comp fa /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ -theorem AnalyticWithinOn.inv {f : E → 𝕝} {s : Set E} - (fa : AnalyticWithinOn 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : - AnalyticWithinOn 𝕜 (fun x ↦ (f x)⁻¹) s := +theorem AnalyticOn.inv {f : E → 𝕝} {s : Set E} + (fa : AnalyticOn 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : + AnalyticOn 𝕜 (fun x ↦ (f x)⁻¹) s := fun x m ↦ (fa x m).inv (f0 x m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.inv := AnalyticOn.inv + /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ -theorem AnalyticOn.inv {f : E → 𝕝} {s : Set E} (fa : AnalyticOn 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : - AnalyticOn 𝕜 (fun x ↦ (f x)⁻¹) s := +theorem AnalyticOnNhd.inv {f : E → 𝕝} {s : Set E} + (fa : AnalyticOnNhd 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : + AnalyticOnNhd 𝕜 (fun x ↦ (f x)⁻¹) s := fun x m ↦ (fa x m).inv (f0 x m) /-- `f x / g x` is analytic away from `g x = 0` -/ @@ -763,18 +818,21 @@ theorem AnalyticAt.div {f g : E → 𝕝} {x : E} AnalyticAt 𝕜 (fun x ↦ f x / g x) x := by simp_rw [div_eq_mul_inv]; exact fa.mul (ga.inv g0) -/-- `f x / g x` is analytic away from `g x = 0` -/ -theorem AnalyticWithinOn.div {f g : E → 𝕝} {s : Set E} - (fa : AnalyticWithinOn 𝕜 f s) (ga : AnalyticWithinOn 𝕜 g s) (g0 : ∀ x ∈ s, g x ≠ 0) : - AnalyticWithinOn 𝕜 (fun x ↦ f x / g x) s := fun x m ↦ - (fa x m).div (ga x m) (g0 x m) - /-- `f x / g x` is analytic away from `g x = 0` -/ theorem AnalyticOn.div {f g : E → 𝕝} {s : Set E} (fa : AnalyticOn 𝕜 f s) (ga : AnalyticOn 𝕜 g s) (g0 : ∀ x ∈ s, g x ≠ 0) : AnalyticOn 𝕜 (fun x ↦ f x / g x) s := fun x m ↦ (fa x m).div (ga x m) (g0 x m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.div := AnalyticOn.div + +/-- `f x / g x` is analytic away from `g x = 0` -/ +theorem AnalyticOnNhd.div {f g : E → 𝕝} {s : Set E} + (fa : AnalyticOnNhd 𝕜 f s) (ga : AnalyticOnNhd 𝕜 g s) (g0 : ∀ x ∈ s, g x ≠ 0) : + AnalyticOnNhd 𝕜 (fun x ↦ f x / g x) s := fun x m ↦ + (fa x m).div (ga x m) (g0 x m) + /-! ### Finite sums and products of analytic functions -/ @@ -797,16 +855,19 @@ theorem Finset.analyticAt_sum {f : α → E → F} {c : E} simp_rw [← analyticWithinAt_univ] at h ⊢ exact N.analyticWithinAt_sum h -/-- Finite sums of analytic functions are analytic -/ -theorem Finset.analyticWithinOn_sum {f : α → E → F} {s : Set E} - (N : Finset α) (h : ∀ n ∈ N, AnalyticWithinOn 𝕜 (f n) s) : - AnalyticWithinOn 𝕜 (fun z ↦ ∑ n ∈ N, f n z) s := - fun z zs ↦ N.analyticWithinAt_sum (fun n m ↦ h n m z zs) - /-- Finite sums of analytic functions are analytic -/ theorem Finset.analyticOn_sum {f : α → E → F} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticOn 𝕜 (f n) s) : AnalyticOn 𝕜 (fun z ↦ ∑ n ∈ N, f n z) s := + fun z zs ↦ N.analyticWithinAt_sum (fun n m ↦ h n m z zs) + +@[deprecated (since := "2024-09-26")] +alias Finset.analyticWithinOn_sum := Finset.analyticOn_sum + +/-- Finite sums of analytic functions are analytic -/ +theorem Finset.analyticOnNhd_sum {f : α → E → F} {s : Set E} + (N : Finset α) (h : ∀ n ∈ N, AnalyticOnNhd 𝕜 (f n) s) : + AnalyticOnNhd 𝕜 (fun z ↦ ∑ n ∈ N, f n z) s := fun z zs ↦ N.analyticAt_sum (fun n m ↦ h n m z zs) /-- Finite products of analytic functions are analytic -/ @@ -827,14 +888,17 @@ theorem Finset.analyticAt_prod {A : Type*} [NormedCommRing A] [NormedAlgebra simp_rw [← analyticWithinAt_univ] at h ⊢ exact N.analyticWithinAt_prod h -/-- Finite products of analytic functions are analytic -/ -theorem Finset.analyticWithinOn_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] - {f : α → E → A} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticWithinOn 𝕜 (f n) s) : - AnalyticWithinOn 𝕜 (fun z ↦ ∏ n ∈ N, f n z) s := - fun z zs ↦ N.analyticWithinAt_prod (fun n m ↦ h n m z zs) - /-- Finite products of analytic functions are analytic -/ theorem Finset.analyticOn_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] {f : α → E → A} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticOn 𝕜 (f n) s) : AnalyticOn 𝕜 (fun z ↦ ∏ n ∈ N, f n z) s := + fun z zs ↦ N.analyticWithinAt_prod (fun n m ↦ h n m z zs) + +@[deprecated (since := "2024-09-26")] +alias Finset.analyticWithinOn_prod := Finset.analyticOn_prod + +/-- Finite products of analytic functions are analytic -/ +theorem Finset.analyticOnNhd_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] + {f : α → E → A} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticOnNhd 𝕜 (f n) s) : + AnalyticOnNhd 𝕜 (fun z ↦ ∏ n ∈ N, f n z) s := fun z zs ↦ N.analyticAt_prod (fun n m ↦ h n m z zs) diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 00ccc0c8bbeea..1f37145b0dc28 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -20,7 +20,7 @@ useful in this setup. * `AnalyticAt.eventually_eq_zero_or_eventually_ne_zero` is the main statement that if a function is analytic at `z₀`, then either it is identically zero in a neighborhood of `z₀`, or it does not vanish in a punctured neighborhood of `z₀`. -* `AnalyticOn.eqOn_of_preconnected_of_frequently_eq` is the identity theorem for analytic +* `AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq` is the identity theorem for analytic functions: if a function `f` is analytic on a connected set `U` and is zero on a set with an accumulation point in `U` then `f` is identically `0` on `U`. -/ @@ -221,7 +221,7 @@ lemma order_eq_nat_iff (hf : AnalyticAt 𝕜 f z₀) (n : ℕ) : hf.order = ↑n end AnalyticAt -namespace AnalyticOn +namespace AnalyticOnNhd variable {U : Set 𝕜} @@ -229,13 +229,13 @@ variable {U : Set 𝕜} analytic on a connected set `U` and vanishes in arbitrary neighborhoods of a point `z₀ ∈ U`, then it is identically zero in `U`. For higher-dimensional versions requiring that the function vanishes in a neighborhood of `z₀`, -see `AnalyticOn.eqOn_zero_of_preconnected_of_eventuallyEq_zero`. -/ -theorem eqOn_zero_of_preconnected_of_frequently_eq_zero (hf : AnalyticOn 𝕜 f U) +see `AnalyticOnNhd.eqOn_zero_of_preconnected_of_eventuallyEq_zero`. -/ +theorem eqOn_zero_of_preconnected_of_frequently_eq_zero (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfw : ∃ᶠ z in 𝓝[≠] z₀, f z = 0) : EqOn f 0 U := hf.eqOn_zero_of_preconnected_of_eventuallyEq_zero hU h₀ ((hf z₀ h₀).frequently_zero_iff_eventually_zero.1 hfw) -theorem eqOn_zero_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hU : IsPreconnected U) +theorem eqOn_zero_of_preconnected_of_mem_closure (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfz₀ : z₀ ∈ closure ({z | f z = 0} \ {z₀})) : EqOn f 0 U := hf.eqOn_zero_of_preconnected_of_frequently_eq_zero hU h₀ (mem_closure_ne_iff_frequently_within.mp hfz₀) @@ -244,15 +244,15 @@ theorem eqOn_zero_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hU analytic on a connected set `U` and coincide at points which accumulate to a point `z₀ ∈ U`, then they coincide globally in `U`. For higher-dimensional versions requiring that the functions coincide in a neighborhood of `z₀`, -see `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`. -/ -theorem eqOn_of_preconnected_of_frequently_eq (hf : AnalyticOn 𝕜 f U) (hg : AnalyticOn 𝕜 g U) +see `AnalyticOnNhd.eqOn_of_preconnected_of_eventuallyEq`. -/ +theorem eqOn_of_preconnected_of_frequently_eq (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfg : ∃ᶠ z in 𝓝[≠] z₀, f z = g z) : EqOn f g U := by have hfg' : ∃ᶠ z in 𝓝[≠] z₀, (f - g) z = 0 := hfg.mono fun z h => by rw [Pi.sub_apply, h, sub_self] simpa [sub_eq_zero] using fun z hz => (hf.sub hg).eqOn_zero_of_preconnected_of_frequently_eq_zero hU h₀ hfg' hz -theorem eqOn_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hg : AnalyticOn 𝕜 g U) +theorem eqOn_of_preconnected_of_mem_closure (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfg : z₀ ∈ closure ({z | f z = g z} \ {z₀})) : EqOn f g U := hf.eqOn_of_preconnected_of_frequently_eq hg hU h₀ (mem_closure_ne_iff_frequently_within.mp hfg) @@ -261,10 +261,13 @@ theorem eqOn_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hg : Ana field `𝕜` are analytic everywhere and coincide at points which accumulate to a point `z₀`, then they coincide globally. For higher-dimensional versions requiring that the functions coincide in a neighborhood of `z₀`, -see `AnalyticOn.eq_of_eventuallyEq`. -/ -theorem eq_of_frequently_eq [ConnectedSpace 𝕜] (hf : AnalyticOn 𝕜 f univ) (hg : AnalyticOn 𝕜 g univ) - (hfg : ∃ᶠ z in 𝓝[≠] z₀, f z = g z) : f = g := +see `AnalyticOnNhd.eq_of_eventuallyEq`. -/ +theorem eq_of_frequently_eq [ConnectedSpace 𝕜] (hf : AnalyticOnNhd 𝕜 f univ) + (hg : AnalyticOnNhd 𝕜 g univ) (hfg : ∃ᶠ z in 𝓝[≠] z₀, f z = g z) : f = g := funext fun x => eqOn_of_preconnected_of_frequently_eq hf hg isPreconnected_univ (mem_univ z₀) hfg (mem_univ x) -end AnalyticOn +@[deprecated (since := "2024-09-26")] +alias _root_.AnalyticOn.eq_of_frequently_eq := eq_of_frequently_eq + +end AnalyticOnNhd diff --git a/Mathlib/Analysis/Analytic/Linear.lean b/Mathlib/Analysis/Analytic/Linear.lean index ee4fa10f65092..e527cda45057c 100644 --- a/Mathlib/Analysis/Analytic/Linear.lean +++ b/Mathlib/Analysis/Analytic/Linear.lean @@ -44,15 +44,18 @@ protected theorem hasFPowerSeriesAt (f : E →L[𝕜] F) (x : E) : protected theorem analyticAt (f : E →L[𝕜] F) (x : E) : AnalyticAt 𝕜 f x := (f.hasFPowerSeriesAt x).analyticAt -protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := +protected theorem analyticOnNhd (f : E →L[𝕜] F) (s : Set E) : AnalyticOnNhd 𝕜 f s := fun x _ ↦ f.analyticAt x protected theorem analyticWithinAt (f : E →L[𝕜] F) (s : Set E) (x : E) : AnalyticWithinAt 𝕜 f s x := (f.analyticAt x).analyticWithinAt -protected theorem analyticWithinOn (f : E →L[𝕜] F) (s : Set E) : AnalyticWithinOn 𝕜 f s := +protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := fun x _ ↦ f.analyticWithinAt _ x +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := ContinuousLinearMap.analyticOn + /-- Reinterpret a bilinear map `f : E →L[𝕜] F →L[𝕜] G` as a multilinear map `(E × F) [×2]→L[𝕜] G`. This multilinear map is the second term in the formal multilinear series expansion of `uncurry f`. It is given by @@ -121,9 +124,17 @@ protected theorem analyticAt_bilinear (f : E →L[𝕜] F →L[𝕜] G) (x : E AnalyticAt 𝕜 (fun x : E × F => f x.1 x.2) x := (f.hasFPowerSeriesAt_bilinear x).analyticAt +protected theorem analyticWithinAt_bilinear (f : E →L[𝕜] F →L[𝕜] G) (s : Set (E × F)) (x : E × F) : + AnalyticWithinAt 𝕜 (fun x : E × F => f x.1 x.2) s x := + (f.analyticAt_bilinear x).analyticWithinAt + +protected theorem analyticOnNhd_bilinear (f : E →L[𝕜] F →L[𝕜] G) (s : Set (E × F)) : + AnalyticOnNhd 𝕜 (fun x : E × F => f x.1 x.2) s := + fun x _ ↦ f.analyticAt_bilinear x + protected theorem analyticOn_bilinear (f : E →L[𝕜] F →L[𝕜] G) (s : Set (E × F)) : AnalyticOn 𝕜 (fun x : E × F => f x.1 x.2) s := - fun x _ ↦ f.analyticAt_bilinear x + (f.analyticOnNhd_bilinear s).analyticOn end ContinuousLinearMap @@ -136,12 +147,15 @@ lemma analyticWithinAt_id : AnalyticWithinAt 𝕜 (id : E → E) s z := analyticAt_id.analyticWithinAt /-- `id` is entire -/ -theorem analyticOn_id : AnalyticOn 𝕜 (fun x : E ↦ x) s := +theorem analyticOnNhd_id : AnalyticOnNhd 𝕜 (fun x : E ↦ x) s := fun _ _ ↦ analyticAt_id -theorem analyticWithinOn_id : AnalyticWithinOn 𝕜 (fun x : E ↦ x) s := +theorem analyticOn_id : AnalyticOn 𝕜 (fun x : E ↦ x) s := fun _ _ ↦ analyticWithinAt_id +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_id := analyticOn_id + /-- `fst` is analytic -/ theorem analyticAt_fst : AnalyticAt 𝕜 (fun p : E × F ↦ p.fst) p := (ContinuousLinearMap.fst 𝕜 E F).analyticAt p @@ -157,19 +171,25 @@ theorem analyticWithinAt_snd : AnalyticWithinAt 𝕜 (fun p : E × F ↦ p.snd) analyticAt_snd.analyticWithinAt /-- `fst` is entire -/ -theorem analyticOn_fst : AnalyticOn 𝕜 (fun p : E × F ↦ p.fst) t := +theorem analyticOnNhd_fst : AnalyticOnNhd 𝕜 (fun p : E × F ↦ p.fst) t := fun _ _ ↦ analyticAt_fst -theorem analyticWithinOn_fst : AnalyticWithinOn 𝕜 (fun p : E × F ↦ p.fst) t := +theorem analyticOn_fst : AnalyticOn 𝕜 (fun p : E × F ↦ p.fst) t := fun _ _ ↦ analyticWithinAt_fst +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_fst := analyticOn_fst + /-- `snd` is entire -/ -theorem analyticOn_snd : AnalyticOn 𝕜 (fun p : E × F ↦ p.snd) t := +theorem analyticOnNhd_snd : AnalyticOnNhd 𝕜 (fun p : E × F ↦ p.snd) t := fun _ _ ↦ analyticAt_snd -theorem analyticWithinOn_snd : AnalyticWithinOn 𝕜 (fun p : E × F ↦ p.snd) t := +theorem analyticOn_snd : AnalyticOn 𝕜 (fun p : E × F ↦ p.snd) t := fun _ _ ↦ analyticWithinAt_snd +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_snd := analyticOn_snd + namespace ContinuousLinearEquiv variable (f : E ≃L[𝕜] F) (s : Set E) (x : E) @@ -177,15 +197,18 @@ variable (f : E ≃L[𝕜] F) (s : Set E) (x : E) protected theorem analyticAt : AnalyticAt 𝕜 f x := ((f : E →L[𝕜] F).hasFPowerSeriesAt x).analyticAt -protected theorem analyticOn : AnalyticOn 𝕜 f s := +protected theorem analyticOnNhd : AnalyticOnNhd 𝕜 f s := fun x _ ↦ f.analyticAt x protected theorem analyticWithinAt (f : E →L[𝕜] F) (s : Set E) (x : E) : AnalyticWithinAt 𝕜 f s x := (f.analyticAt x).analyticWithinAt -protected theorem analyticWithinOn (f : E →L[𝕜] F) (s : Set E) : AnalyticWithinOn 𝕜 f s := +protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := fun x _ ↦ f.analyticWithinAt _ x +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := ContinuousLinearEquiv.analyticOn + end ContinuousLinearEquiv namespace LinearIsometryEquiv @@ -195,13 +218,16 @@ variable (f : E ≃ₗᵢ[𝕜] F) (s : Set E) (x : E) protected theorem analyticAt : AnalyticAt 𝕜 f x := ((f : E →L[𝕜] F).hasFPowerSeriesAt x).analyticAt -protected theorem analyticOn : AnalyticOn 𝕜 f s := +protected theorem analyticOnNhd : AnalyticOnNhd 𝕜 f s := fun x _ ↦ f.analyticAt x protected theorem analyticWithinAt (f : E →L[𝕜] F) (s : Set E) (x : E) : AnalyticWithinAt 𝕜 f s x := (f.analyticAt x).analyticWithinAt -protected theorem analyticWithinOn (f : E →L[𝕜] F) (s : Set E) : AnalyticWithinOn 𝕜 f s := +protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := fun x _ ↦ f.analyticWithinAt _ x +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := LinearIsometryEquiv.analyticOn + end LinearIsometryEquiv diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean index 1a29b6bb5cff9..4c3349d87d078 100644 --- a/Mathlib/Analysis/Analytic/Meromorphic.lean +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -237,10 +237,12 @@ end MeromorphicAt /-- Meromorphy of a function on a set. -/ def MeromorphicOn (f : 𝕜 → E) (U : Set 𝕜) : Prop := ∀ x ∈ U, MeromorphicAt f x -lemma AnalyticOn.meromorphicOn {f : 𝕜 → E} {U : Set 𝕜} (hf : AnalyticOn 𝕜 f U) : +lemma AnalyticOnNhd.meromorphicOn {f : 𝕜 → E} {U : Set 𝕜} (hf : AnalyticOnNhd 𝕜 f U) : MeromorphicOn f U := fun x hx ↦ (hf x hx).meromorphicAt +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.meromorphicOn := AnalyticOnNhd.meromorphicOn namespace MeromorphicOn diff --git a/Mathlib/Analysis/Analytic/Polynomial.lean b/Mathlib/Analysis/Analytic/Polynomial.lean index 74ea377c682ac..77e62fd5b542b 100644 --- a/Mathlib/Analysis/Analytic/Polynomial.lean +++ b/Mathlib/Analysis/Analytic/Polynomial.lean @@ -23,17 +23,28 @@ open Polynomial variable [NormedRing B] [NormedAlgebra 𝕜 B] [Algebra A B] {f : E → B} -theorem AnalyticAt.aeval_polynomial (hf : AnalyticAt 𝕜 f z) (p : A[X]) : - AnalyticAt 𝕜 (fun x ↦ aeval (f x) p) z := by +theorem AnalyticWithinAt.aeval_polynomial (hf : AnalyticWithinAt 𝕜 f s z) (p : A[X]) : + AnalyticWithinAt 𝕜 (fun x ↦ aeval (f x) p) s z := by refine p.induction_on (fun k ↦ ?_) (fun p q hp hq ↦ ?_) fun p i hp ↦ ?_ - · simp_rw [aeval_C]; apply analyticAt_const + · simp_rw [aeval_C]; apply analyticWithinAt_const · simp_rw [aeval_add]; exact hp.add hq · convert hp.mul hf simp_rw [pow_succ, aeval_mul, ← mul_assoc, aeval_X] +theorem AnalyticAt.aeval_polynomial (hf : AnalyticAt 𝕜 f z) (p : A[X]) : + AnalyticAt 𝕜 (fun x ↦ aeval (f x) p) z := by + rw [← analyticWithinAt_univ] at hf ⊢ + exact hf.aeval_polynomial p + +theorem AnalyticOnNhd.aeval_polynomial (hf : AnalyticOnNhd 𝕜 f s) (p : A[X]) : + AnalyticOnNhd 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ (hf x hx).aeval_polynomial p + theorem AnalyticOn.aeval_polynomial (hf : AnalyticOn 𝕜 f s) (p : A[X]) : AnalyticOn 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ (hf x hx).aeval_polynomial p +theorem AnalyticOnNhd.eval_polynomial {A} [NormedCommRing A] [NormedAlgebra 𝕜 A] (p : A[X]) : + AnalyticOnNhd 𝕜 (eval · p) Set.univ := analyticOnNhd_id.aeval_polynomial p + theorem AnalyticOn.eval_polynomial {A} [NormedCommRing A] [NormedAlgebra 𝕜 A] (p : A[X]) : AnalyticOn 𝕜 (eval · p) Set.univ := analyticOn_id.aeval_polynomial p @@ -51,27 +62,47 @@ theorem AnalyticAt.aeval_mvPolynomial (hf : ∀ i, AnalyticAt 𝕜 (f · i) z) ( · simp_rw [map_add]; exact hp.add hq · simp_rw [map_mul, aeval_X]; exact hp.mul (hf i) -theorem AnalyticOn.aeval_mvPolynomial (hf : ∀ i, AnalyticOn 𝕜 (f · i) s) (p : MvPolynomial σ A) : - AnalyticOn 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ .aeval_mvPolynomial (hf · x hx) p +theorem AnalyticOnNhd.aeval_mvPolynomial + (hf : ∀ i, AnalyticOnNhd 𝕜 (f · i) s) (p : MvPolynomial σ A) : + AnalyticOnNhd 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ .aeval_mvPolynomial (hf · x hx) p + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.aeval_mvPolynomial := AnalyticOnNhd.aeval_mvPolynomial -theorem AnalyticOn.eval_continuousLinearMap (f : E →L[𝕜] σ → B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f x) p) Set.univ := +theorem AnalyticOnNhd.eval_continuousLinearMap (f : E →L[𝕜] σ → B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f x) p) Set.univ := fun x _ ↦ .aeval_mvPolynomial (fun i ↦ ((ContinuousLinearMap.proj i).comp f).analyticAt x) p -theorem AnalyticOn.eval_continuousLinearMap' (f : σ → E →L[𝕜] B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f · x) p) Set.univ := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_continuousLinearMap := AnalyticOnNhd.eval_continuousLinearMap + +theorem AnalyticOnNhd.eval_continuousLinearMap' (f : σ → E →L[𝕜] B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f · x) p) Set.univ := fun x _ ↦ .aeval_mvPolynomial (fun i ↦ (f i).analyticAt x) p +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_continuousLinearMap' := AnalyticOnNhd.eval_continuousLinearMap' + variable [CompleteSpace 𝕜] [T2Space E] [FiniteDimensional 𝕜 E] -theorem AnalyticOn.eval_linearMap (f : E →ₗ[𝕜] σ → B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f x) p) Set.univ := - AnalyticOn.eval_continuousLinearMap { f with cont := f.continuous_of_finiteDimensional } p +theorem AnalyticOnNhd.eval_linearMap (f : E →ₗ[𝕜] σ → B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f x) p) Set.univ := + AnalyticOnNhd.eval_continuousLinearMap { f with cont := f.continuous_of_finiteDimensional } p + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_linearMap := AnalyticOnNhd.eval_linearMap + +theorem AnalyticOnNhd.eval_linearMap' (f : σ → E →ₗ[𝕜] B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f · x) p) Set.univ := AnalyticOnNhd.eval_linearMap (.pi f) p + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_linearMap' := AnalyticOnNhd.eval_linearMap' -theorem AnalyticOn.eval_linearMap' (f : σ → E →ₗ[𝕜] B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f · x) p) Set.univ := AnalyticOn.eval_linearMap (.pi f) p +theorem AnalyticOnNhd.eval_mvPolynomial [Fintype σ] (p : MvPolynomial σ 𝕜) : + AnalyticOnNhd 𝕜 (eval · p) Set.univ := + AnalyticOnNhd.eval_linearMap (.id (R := 𝕜) (M := σ → 𝕜)) p -theorem AnalyticOn.eval_mvPolynomial [Fintype σ] (p : MvPolynomial σ 𝕜) : - AnalyticOn 𝕜 (eval · p) Set.univ := AnalyticOn.eval_linearMap (.id (R := 𝕜) (M := σ → 𝕜)) p +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_mvPolynomial := AnalyticOnNhd.eval_mvPolynomial end MvPolynomial diff --git a/Mathlib/Analysis/Analytic/Uniqueness.lean b/Mathlib/Analysis/Analytic/Uniqueness.lean index 088cf07ea867d..6c836c8afcab6 100644 --- a/Mathlib/Analysis/Analytic/Uniqueness.lean +++ b/Mathlib/Analysis/Analytic/Uniqueness.lean @@ -13,7 +13,7 @@ import Mathlib.Analysis.Analytic.ChangeOrigin # Uniqueness principle for analytic functions We show that two analytic functions which coincide around a point coincide on whole connected sets, -in `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`. +in `AnalyticOnNhd.eqOn_of_preconnected_of_eventuallyEq`. -/ @@ -154,13 +154,14 @@ theorem HasFPowerSeriesOnBall.r_eq_top_of_exists {f : 𝕜 → E} {r : ℝ≥0 end Uniqueness -namespace AnalyticOn +namespace AnalyticOnNhd /-- If an analytic function vanishes around a point, then it is uniformly zero along a connected set. Superseded by `eqOn_zero_of_preconnected_of_locally_zero` which does not assume completeness of the target space. -/ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero_aux [CompleteSpace F] {f : E → F} {U : Set E} - (hf : AnalyticOn 𝕜 f U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : + (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) + {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : EqOn f 0 U := by /- Let `u` be the set of points around which `f` vanishes. It is clearly open. We have to show that its limit points in `U` still belong to it, from which the inclusion `U ⊆ u` will follow @@ -204,11 +205,12 @@ neighborhood of a point `z₀`, then it is uniformly zero along a connected set. version assuming only that the function vanishes at some points arbitrarily close to `z₀`, see `eqOn_zero_of_preconnected_of_frequently_eq_zero`. -/ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero {f : E → F} {U : Set E} - (hf : AnalyticOn 𝕜 f U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : + (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) + {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : EqOn f 0 U := by let F' := UniformSpace.Completion F set e : F →L[𝕜] F' := UniformSpace.Completion.toComplL - have : AnalyticOn 𝕜 (e ∘ f) U := fun x hx => (e.analyticAt _).comp (hf x hx) + have : AnalyticOnNhd 𝕜 (e ∘ f) U := fun x hx => (e.analyticAt _).comp (hf x hx) have A : EqOn (e ∘ f) 0 U := by apply eqOn_zero_of_preconnected_of_eventuallyEq_zero_aux this hU h₀ filter_upwards [hfz₀] with x hx @@ -221,8 +223,8 @@ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero {f : E → F} {U : Set E} neighborhood of a point `z₀`, then they coincide globally along a connected set. For a one-dimensional version assuming only that the functions coincide at some points arbitrarily close to `z₀`, see `eqOn_of_preconnected_of_frequently_eq`. -/ -theorem eqOn_of_preconnected_of_eventuallyEq {f g : E → F} {U : Set E} (hf : AnalyticOn 𝕜 f U) - (hg : AnalyticOn 𝕜 g U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfg : f =ᶠ[𝓝 z₀] g) : +theorem eqOn_of_preconnected_of_eventuallyEq {f g : E → F} {U : Set E} (hf : AnalyticOnNhd 𝕜 f U) + (hg : AnalyticOnNhd 𝕜 g U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfg : f =ᶠ[𝓝 z₀] g) : EqOn f g U := by have hfg' : f - g =ᶠ[𝓝 z₀] 0 := hfg.mono fun z h => by simp [h] simpa [sub_eq_zero] using fun z hz => @@ -232,9 +234,9 @@ theorem eqOn_of_preconnected_of_eventuallyEq {f g : E → F} {U : Set E} (hf : A coincide in a neighborhood of a point `z₀`, then they coincide everywhere. For a one-dimensional version assuming only that the functions coincide at some points arbitrarily close to `z₀`, see `eq_of_frequently_eq`. -/ -theorem eq_of_eventuallyEq {f g : E → F} [PreconnectedSpace E] (hf : AnalyticOn 𝕜 f univ) - (hg : AnalyticOn 𝕜 g univ) {z₀ : E} (hfg : f =ᶠ[𝓝 z₀] g) : f = g := +theorem eq_of_eventuallyEq {f g : E → F} [PreconnectedSpace E] (hf : AnalyticOnNhd 𝕜 f univ) + (hg : AnalyticOnNhd 𝕜 g univ) {z₀ : E} (hfg : f =ᶠ[𝓝 z₀] g) : f = g := funext fun x => eqOn_of_preconnected_of_eventuallyEq hf hg isPreconnected_univ (mem_univ z₀) hfg (mem_univ x) -end AnalyticOn +end AnalyticOnNhd diff --git a/Mathlib/Analysis/Analytic/Within.lean b/Mathlib/Analysis/Analytic/Within.lean index 7b1093877a659..7703eb9524ef0 100644 --- a/Mathlib/Analysis/Analytic/Within.lean +++ b/Mathlib/Analysis/Analytic/Within.lean @@ -11,7 +11,7 @@ import Mathlib.Analysis.Analytic.Constructions From `Mathlib.Analysis.Analytic.Basic`, we have the definitions 1. `AnalyticWithinAt 𝕜 f s x` means a power series at `x` converges to `f` on `𝓝[insert x s] x`. -2. `AnalyticWithinOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. +2. `AnalyticOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. This means there exists an extension of `f` which is analytic and agrees with `f` on `s ∪ {x}`, but `f` is allowed to be arbitrary elsewhere. @@ -56,10 +56,10 @@ lemma analyticWithinAt_of_singleton_mem {f : E → F} {s : Set E} {x : E} (h : { apply (hasFPowerSeriesOnBall_const (e := 0)).hasSum simp only [Metric.emetric_ball_top, mem_univ] }⟩ -/-- If `f` is `AnalyticWithinOn` near each point in a set, it is `AnalyticWithinOn` the set -/ -lemma analyticWithinOn_of_locally_analyticWithinOn {f : E → F} {s : Set E} - (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ AnalyticWithinOn 𝕜 f (s ∩ u)) : - AnalyticWithinOn 𝕜 f s := by +/-- If `f` is `AnalyticOn` near each point in a set, it is `AnalyticOn` the set -/ +lemma analyticOn_of_locally_analyticOn {f : E → F} {s : Set E} + (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ AnalyticOn 𝕜 f (s ∩ u)) : + AnalyticOn 𝕜 f s := by intro x m rcases h x m with ⟨u, ou, xu, fu⟩ rcases Metric.mem_nhds_iff.mp (ou.mem_nhds xu) with ⟨r, r0, ru⟩ @@ -79,10 +79,13 @@ lemma analyticWithinOn_of_locally_analyticWithinOn {f : E → F} {s : Set E} simp only [Metric.mem_ball, dist_self_add_left, yr] · simp only [EMetric.mem_ball, yr] }⟩ -/-- On open sets, `AnalyticOn` and `AnalyticWithinOn` coincide -/ -lemma IsOpen.analyticWithinOn_iff_analyticOn {f : E → F} {s : Set E} (hs : IsOpen s) : - AnalyticWithinOn 𝕜 f s ↔ AnalyticOn 𝕜 f s := by - refine ⟨?_, AnalyticOn.analyticWithinOn⟩ +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_of_locally_analyticWithinOn := analyticOn_of_locally_analyticOn + +/-- On open sets, `AnalyticOnNhd` and `AnalyticOn` coincide -/ +lemma IsOpen.analyticOn_iff_analyticOnNhd {f : E → F} {s : Set E} (hs : IsOpen s) : + AnalyticOn 𝕜 f s ↔ AnalyticOnNhd 𝕜 f s := by + refine ⟨?_, AnalyticOnNhd.analyticOn⟩ intro hf x m rcases Metric.mem_nhds_iff.mp (hs.mem_nhds m) with ⟨r, r0, rs⟩ rcases hf x m with ⟨p, t, fp⟩ @@ -97,13 +100,16 @@ lemma IsOpen.analyticWithinOn_iff_analyticOn {f : E → F} {s : Set E} (hs : IsO apply rs simp only [Metric.mem_ball, dist_self_add_left, ym.1] }⟩ +@[deprecated (since := "2024-09-26")] +alias IsOpen.analyticWithinOn_iff_analyticOn := IsOpen.analyticOn_iff_analyticOnNhd + /-! ### Equivalence to analyticity of a local extension We show that `HasFPowerSeriesWithinOnBall`, `HasFPowerSeriesWithinAt`, and `AnalyticWithinAt` are equivalent to the existence of a local extension with full analyticity. We do not yet show a -result for `AnalyticWithinOn`, as this requires a bit more work to show that local extensions can +result for `AnalyticOn`, as this requires a bit more work to show that local extensions can be stitched together. -/ diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index ef38ec6312a71..896125484853c 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -68,9 +68,13 @@ theorem HasFPowerSeriesOnBall.differentiableOn [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) : DifferentiableOn 𝕜 f (EMetric.ball x r) := fun _ hy => (h.analyticAt_of_mem hy).differentiableWithinAt -theorem AnalyticOn.differentiableOn (h : AnalyticOn 𝕜 f s) : DifferentiableOn 𝕜 f s := fun y hy => +theorem AnalyticOnNhd.differentiableOn (h : AnalyticOnNhd 𝕜 f s) : + DifferentiableOn 𝕜 f s := fun y hy => (h y hy).differentiableWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.differentiableOn := AnalyticOnNhd.differentiableOn + theorem HasFPowerSeriesOnBall.hasFDerivAt [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) : HasFDerivAt f (continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin y 1)) (x + y) := @@ -95,32 +99,38 @@ theorem HasFPowerSeriesOnBall.fderiv [CompleteSpace F] (h : HasFPowerSeriesOnBal simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz /-- If a function is analytic on a set `s`, so is its Fréchet derivative. -/ -theorem AnalyticOn.fderiv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (fderiv 𝕜 f) s := by +theorem AnalyticOnNhd.fderiv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (fderiv 𝕜 f) s := by intro y hy rcases h y hy with ⟨p, r, hp⟩ exact hp.fderiv.analyticAt +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.fderiv := AnalyticOnNhd.fderiv + /-- If a function is analytic on a set `s`, so are its successive Fréchet derivative. -/ -theorem AnalyticOn.iteratedFDeriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) (n : ℕ) : - AnalyticOn 𝕜 (iteratedFDeriv 𝕜 n f) s := by +theorem AnalyticOnNhd.iteratedFDeriv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) (n : ℕ) : + AnalyticOnNhd 𝕜 (iteratedFDeriv 𝕜 n f) s := by induction n with | zero => rw [iteratedFDeriv_zero_eq_comp] - exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F).comp_analyticOn h + exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F).comp_analyticOnNhd h | succ n IH => rw [iteratedFDeriv_succ_eq_comp_left] -- Porting note: for reasons that I do not understand at all, `?g` cannot be inlined. - convert ContinuousLinearMap.comp_analyticOn ?g IH.fderiv + convert ContinuousLinearMap.comp_analyticOnNhd ?g IH.fderiv case g => exact ↑(continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (n + 1) ↦ E) F).symm simp +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.iteratedFDeriv := AnalyticOnNhd.iteratedFDeriv + /-- An analytic function is infinitely differentiable. -/ -theorem AnalyticOn.contDiffOn [CompleteSpace F] (h : AnalyticOn 𝕜 f s) {n : ℕ∞} : +theorem AnalyticOnNhd.contDiffOn [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := let t := { x | AnalyticAt 𝕜 f x } suffices ContDiffOn 𝕜 n f t from this.mono h - have H : AnalyticOn 𝕜 f t := fun _x hx ↦ hx + have H : AnalyticOnNhd 𝕜 f t := fun _x hx ↦ hx have t_open : IsOpen t := isOpen_analyticAt 𝕜 f contDiffOn_of_continuousOn_differentiableOn (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr @@ -130,7 +140,7 @@ theorem AnalyticOn.contDiffOn [CompleteSpace F] (h : AnalyticOn 𝕜 f s) {n : theorem AnalyticAt.contDiffAt [CompleteSpace F] (h : AnalyticAt 𝕜 f x) {n : ℕ∞} : ContDiffAt 𝕜 n f x := by - obtain ⟨s, hs, hf⟩ := h.exists_mem_nhds_analyticOn + obtain ⟨s, hs, hf⟩ := h.exists_mem_nhds_analyticOnNhd exact hf.contDiffOn.contDiffAt hs lemma AnalyticWithinAt.contDiffWithinAt [CompleteSpace F] {f : E → F} {s : Set E} {x : E} @@ -138,10 +148,13 @@ lemma AnalyticWithinAt.contDiffWithinAt [CompleteSpace F] {f : E → F} {s : Set rcases h.exists_analyticAt with ⟨g, fx, fg, hg⟩ exact hg.contDiffAt.contDiffWithinAt.congr (fg.mono (subset_insert _ _)) fx -lemma AnalyticWithinOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E} - (h : AnalyticWithinOn 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := +lemma AnalyticOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E} + (h : AnalyticOn 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := fun x m ↦ (h x m).contDiffWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.contDiffOn := AnalyticOn.contDiffOn + end fderiv section deriv @@ -162,16 +175,23 @@ protected theorem HasFPowerSeriesAt.deriv (h : HasFPowerSeriesAt f p x) : h.hasDerivAt.deriv /-- If a function is analytic on a set `s`, so is its derivative. -/ -theorem AnalyticOn.deriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (deriv f) s := - (ContinuousLinearMap.apply 𝕜 F (1 : 𝕜)).comp_analyticOn h.fderiv +theorem AnalyticOnNhd.deriv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (deriv f) s := + (ContinuousLinearMap.apply 𝕜 F (1 : 𝕜)).comp_analyticOnNhd h.fderiv + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.deriv := AnalyticOnNhd.deriv /-- If a function is analytic on a set `s`, so are its successive derivatives. -/ -theorem AnalyticOn.iterated_deriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) (n : ℕ) : - AnalyticOn 𝕜 (_root_.deriv^[n] f) s := by +theorem AnalyticOnNhd.iterated_deriv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) (n : ℕ) : + AnalyticOnNhd 𝕜 (_root_.deriv^[n] f) s := by induction n with | zero => exact h | succ n IH => simpa only [Function.iterate_succ', Function.comp_apply] using IH.deriv +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.iterated_deriv := AnalyticOnNhd.iterated_deriv + end deriv section fderiv @@ -258,7 +278,7 @@ theorem CPolynomialOn.contDiffOn (h : CPolynomialOn 𝕜 f s) {n : ℕ∞} : contDiffOn_of_continuousOn_differentiableOn (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) - (fun m _ ↦ (H.iteratedFDeriv m).analyticOn.differentiableOn.congr + (fun m _ ↦ (H.iteratedFDeriv m).analyticOnNhd.differentiableOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) theorem CPolynomialAt.contDiffAt (h : CPolynomialAt 𝕜 f x) {n : ℕ∞} : diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index acb07715c395f..ebc991f8801e8 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -568,14 +568,18 @@ protected theorem _root_.DifferentiableOn.analyticAt {s : Set ℂ} {f : ℂ → lift R to ℝ≥0 using hR0.le exact ((hd.mono hRs).hasFPowerSeriesOnBall hR0).analyticAt +theorem _root_.DifferentiableOn.analyticOnNhd {s : Set ℂ} {f : ℂ → E} (hd : DifferentiableOn ℂ f s) + (hs : IsOpen s) : AnalyticOnNhd ℂ f s := fun _z hz => hd.analyticAt (hs.mem_nhds hz) + theorem _root_.DifferentiableOn.analyticOn {s : Set ℂ} {f : ℂ → E} (hd : DifferentiableOn ℂ f s) - (hs : IsOpen s) : AnalyticOn ℂ f s := fun _z hz => hd.analyticAt (hs.mem_nhds hz) + (hs : IsOpen s) : AnalyticOn ℂ f s := + (hd.analyticOnNhd hs).analyticOn /-- If `f : ℂ → E` is complex differentiable on some open set `s`, then it is continuously differentiable on `s`. -/ protected theorem _root_.DifferentiableOn.contDiffOn {s : Set ℂ} {f : ℂ → E} {n : ℕ} (hd : DifferentiableOn ℂ f s) (hs : IsOpen s) : ContDiffOn ℂ n f s := - (hd.analyticOn hs).contDiffOn + (hd.analyticOnNhd hs).contDiffOn /-- A complex differentiable function `f : ℂ → E` is analytic at every point. -/ protected theorem _root_.Differentiable.analyticAt {f : ℂ → E} (hf : Differentiable ℂ f) (z : ℂ) : @@ -594,16 +598,27 @@ protected theorem _root_.Differentiable.hasFPowerSeriesOnBall {f : ℂ → E} (h (h.differentiableOn.hasFPowerSeriesOnBall hR).r_eq_top_of_exists fun _r hr => ⟨_, h.differentiableOn.hasFPowerSeriesOnBall hr⟩ +/-- On an open set, `f : ℂ → E` is analytic iff it is differentiable -/ +theorem analyticOnNhd_iff_differentiableOn {f : ℂ → E} {s : Set ℂ} (o : IsOpen s) : + AnalyticOnNhd ℂ f s ↔ DifferentiableOn ℂ f s := + ⟨AnalyticOnNhd.differentiableOn, fun d _ zs ↦ d.analyticAt (o.mem_nhds zs)⟩ + /-- On an open set, `f : ℂ → E` is analytic iff it is differentiable -/ theorem analyticOn_iff_differentiableOn {f : ℂ → E} {s : Set ℂ} (o : IsOpen s) : - AnalyticOn ℂ f s ↔ DifferentiableOn ℂ f s := - ⟨AnalyticOn.differentiableOn, fun d _ zs ↦ d.analyticAt (o.mem_nhds zs)⟩ + AnalyticOn ℂ f s ↔ DifferentiableOn ℂ f s := by + rw [o.analyticOn_iff_analyticOnNhd] + exact analyticOnNhd_iff_differentiableOn o /-- `f : ℂ → E` is entire iff it's differentiable -/ +theorem analyticOnNhd_univ_iff_differentiable {f : ℂ → E} : + AnalyticOnNhd ℂ f univ ↔ Differentiable ℂ f := by + simp only [← differentiableOn_univ] + exact analyticOnNhd_iff_differentiableOn isOpen_univ + theorem analyticOn_univ_iff_differentiable {f : ℂ → E} : AnalyticOn ℂ f univ ↔ Differentiable ℂ f := by - simp only [← differentiableOn_univ] - exact analyticOn_iff_differentiableOn isOpen_univ + rw [analyticOn_univ] + exact analyticOnNhd_univ_iff_differentiable /-- `f : ℂ → E` is analytic at `z` iff it's differentiable near `z` -/ theorem analyticAt_iff_eventually_differentiableAt {f : ℂ → E} {c : ℂ} : @@ -614,8 +629,8 @@ theorem analyticAt_iff_eventually_differentiableAt {f : ℂ → E} {c : ℂ} : apply AnalyticAt.differentiableAt · intro d rcases _root_.eventually_nhds_iff.mp d with ⟨s, d, o, m⟩ - have h : AnalyticOn ℂ f s := by - refine DifferentiableOn.analyticOn ?_ o + have h : AnalyticOnNhd ℂ f s := by + refine DifferentiableOn.analyticOnNhd ?_ o intro z m exact (d z m).differentiableWithinAt exact h _ m diff --git a/Mathlib/Analysis/Complex/OpenMapping.lean b/Mathlib/Analysis/Complex/OpenMapping.lean index 9ce4d01945319..c37d82d1058c9 100644 --- a/Mathlib/Analysis/Complex/OpenMapping.lean +++ b/Mathlib/Analysis/Complex/OpenMapping.lean @@ -27,7 +27,7 @@ That second step is implemented in `DiffContOnCl.ball_subset_image_closedBall`. * `AnalyticAt.eventually_constant_or_nhds_le_map_nhds` is the local version of the open mapping theorem around a point; -* `AnalyticOn.is_constant_or_isOpen` is the open mapping theorem on a connected open set. +* `AnalyticOnNhd.is_constant_or_isOpen` is the open mapping theorem on a connected open set. -/ @@ -51,7 +51,7 @@ theorem DiffContOnCl.ball_subset_image_closedBall (h : DiffContOnCl ℂ f (ball have h1 : DiffContOnCl ℂ (fun z => f z - v) (ball z₀ r) := h.sub_const v have h2 : ContinuousOn (fun z => ‖f z - v‖) (closedBall z₀ r) := continuous_norm.comp_continuousOn (closure_ball z₀ hr.ne.symm ▸ h1.continuousOn) - have h3 : AnalyticOn ℂ f (ball z₀ r) := h.differentiableOn.analyticOn isOpen_ball + have h3 : AnalyticOnNhd ℂ f (ball z₀ r) := h.differentiableOn.analyticOnNhd isOpen_ball have h4 : ∀ z ∈ sphere z₀ r, ε / 2 ≤ ‖f z - v‖ := fun z hz => by linarith [hf z hz, show ‖v - f z₀‖ < ε / 2 from mem_ball.mp hv, norm_sub_sub_norm_sub_le_norm_sub (f z) v (f z₀)] @@ -64,7 +64,7 @@ theorem DiffContOnCl.ball_subset_image_closedBall (h : DiffContOnCl ℂ f (ball have h7 : ∀ᶠ w in 𝓝 z, f w = f z := by filter_upwards [key] with h; field_simp replace h7 : ∃ᶠ w in 𝓝[≠] z, f w = f z := (h7.filter_mono nhdsWithin_le_nhds).frequently have h8 : IsPreconnected (ball z₀ r) := (convex_ball z₀ r).isPreconnected - have h9 := h3.eqOn_of_preconnected_of_frequently_eq analyticOn_const h8 hz1 h7 + have h9 := h3.eqOn_of_preconnected_of_frequently_eq analyticOnNhd_const h8 hz1 h7 have h10 : f z = f z₀ := (h9 (mem_ball_self hr)).symm exact not_eventually.mpr hz₀ (mem_of_superset (ball_mem_nhds z₀ hr) (h10 ▸ h9)) @@ -83,7 +83,7 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds_aux (hf : AnalyticAt have h1 := (hf.eventually_eq_or_eventually_ne analyticAt_const).resolve_left h have h2 : ∀ᶠ z in 𝓝 z₀, AnalyticAt ℂ f z := (isOpen_analyticAt ℂ f).eventually_mem hf obtain ⟨ρ, hρ, h3, h4⟩ : - ∃ ρ > 0, AnalyticOn ℂ f (closedBall z₀ ρ) ∧ ∀ z ∈ closedBall z₀ ρ, z ≠ z₀ → f z ≠ f z₀ := by + ∃ ρ > 0, AnalyticOnNhd ℂ f (closedBall z₀ ρ) ∧ ∀ z ∈ closedBall z₀ ρ, z ≠ z₀ → f z ≠ f z₀ := by simpa only [setOf_and, subset_inter_iff] using nhds_basis_closedBall.mem_iff.mp (h2.and (eventually_nhdsWithin_iff.mp h1)) replace h3 : DiffContOnCl ℂ f (ball z₀ ρ) := @@ -118,7 +118,7 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds {z₀ : E} (hg : Anal let ray : E → ℂ → E := fun z t => z₀ + t • z let gray : E → ℂ → ℂ := fun z => g ∘ ray z obtain ⟨r, hr, hgr⟩ := isOpen_iff.mp (isOpen_analyticAt ℂ g) z₀ hg - have h1 : ∀ z ∈ sphere (0 : E) 1, AnalyticOn ℂ (gray z) (ball 0 r) := by + have h1 : ∀ z ∈ sphere (0 : E) 1, AnalyticOnNhd ℂ (gray z) (ball 0 r) := by refine fun z hz t ht => AnalyticAt.comp ?_ ?_ · exact hgr (by simpa [ray, norm_smul, mem_sphere_zero_iff_norm.mp hz] using ht) · exact analyticAt_const.add @@ -134,7 +134,7 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds {z₀ : E} (hg : Anal have e1 : IsPreconnected (ball (0 : ℂ) r) := (convex_ball 0 r).isPreconnected have e2 : w ∈ sphere (0 : E) 1 := by simp [w, norm_smul, inv_mul_cancel₀ h'] specialize h1 w e2 - apply h1.eqOn_of_preconnected_of_eventuallyEq analyticOn_const e1 (mem_ball_self hr) + apply h1.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const e1 (mem_ball_self hr) simpa [ray, gray] using h w e2 have h4 : ‖z - z₀‖ < r := by simpa [dist_eq_norm] using mem_ball.mp hz replace h4 : ↑‖z - z₀‖ ∈ ball (0 : ℂ) r := by @@ -156,13 +156,16 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds {z₀ : E} (hg : Anal /-- The *open mapping theorem* for holomorphic functions, global version: if a function `g : E → ℂ` is analytic on a connected set `U`, then either it is constant on `U`, or it is open on `U` (in the sense that it maps any open set contained in `U` to an open set in `ℂ`). -/ -theorem AnalyticOn.is_constant_or_isOpen (hg : AnalyticOn ℂ g U) (hU : IsPreconnected U) : +theorem AnalyticOnNhd.is_constant_or_isOpen (hg : AnalyticOnNhd ℂ g U) (hU : IsPreconnected U) : (∃ w, ∀ z ∈ U, g z = w) ∨ ∀ s ⊆ U, IsOpen s → IsOpen (g '' s) := by by_cases h : ∃ z₀ ∈ U, ∀ᶠ z in 𝓝 z₀, g z = g z₀ · obtain ⟨z₀, hz₀, h⟩ := h - exact Or.inl ⟨g z₀, hg.eqOn_of_preconnected_of_eventuallyEq analyticOn_const hU hz₀ h⟩ + exact Or.inl ⟨g z₀, hg.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const hU hz₀ h⟩ · push_neg at h refine Or.inr fun s hs1 hs2 => isOpen_iff_mem_nhds.mpr ?_ rintro z ⟨w, hw1, rfl⟩ exact (hg w (hs1 hw1)).eventually_constant_or_nhds_le_map_nhds.resolve_left (h w (hs1 hw1)) (image_mem_map (hs2.mem_nhds hw1)) + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.is_constant_or_isOpen := AnalyticOnNhd.is_constant_or_isOpen diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean index 18ea3db3671d5..dfa5088bf9e96 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean @@ -21,21 +21,30 @@ variable {E : Type} [NormedAddCommGroup E] [NormedSpace ℂ E] variable {f g : E → ℂ} {z : ℂ} {x : E} {s : Set E} /-- `exp` is entire -/ -theorem analyticOn_cexp : AnalyticOn ℂ exp univ := by - rw [analyticOn_univ_iff_differentiable]; exact differentiable_exp +theorem analyticOnNhd_cexp : AnalyticOnNhd ℂ exp univ := by + rw [analyticOnNhd_univ_iff_differentiable]; exact differentiable_exp + +theorem analyticOn_cexp : AnalyticOn ℂ exp univ := analyticOnNhd_cexp.analyticOn /-- `exp` is analytic at any point -/ theorem analyticAt_cexp : AnalyticAt ℂ exp z := - analyticOn_cexp z (mem_univ _) + analyticOnNhd_cexp z (mem_univ _) /-- `exp ∘ f` is analytic -/ theorem AnalyticAt.cexp (fa : AnalyticAt ℂ f x) : AnalyticAt ℂ (fun z ↦ exp (f z)) x := analyticAt_cexp.comp fa +theorem AnalyticWithinAt.cexp (fa : AnalyticWithinAt ℂ f s x) : + AnalyticWithinAt ℂ (fun z ↦ exp (f z)) s x := + analyticAt_cexp.comp_analyticWithinAt fa + /-- `exp ∘ f` is analytic -/ -theorem AnalyticOn.cexp (fs : AnalyticOn ℂ f s) : AnalyticOn ℂ (fun z ↦ exp (f z)) s := +theorem AnalyticOnNhd.cexp (fs : AnalyticOnNhd ℂ f s) : AnalyticOnNhd ℂ (fun z ↦ exp (f z)) s := fun z n ↦ analyticAt_cexp.comp (fs z n) +theorem AnalyticOn.cexp (fs : AnalyticOn ℂ f s) : AnalyticOn ℂ (fun z ↦ exp (f z)) s := + analyticOnNhd_cexp.comp_analyticOn fs (mapsTo_univ _ _) + /-- `log` is analytic away from nonpositive reals -/ theorem analyticAt_clog (m : z ∈ slitPlane) : AnalyticAt ℂ log z := by rw [analyticAt_iff_eventually_differentiableAt] @@ -48,21 +57,40 @@ theorem AnalyticAt.clog (fa : AnalyticAt ℂ f x) (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ log (f z)) x := (analyticAt_clog m).comp fa +theorem AnalyticWithinAt.clog (fa : AnalyticWithinAt ℂ f s x) (m : f x ∈ slitPlane) : + AnalyticWithinAt ℂ (fun z ↦ log (f z)) s x := + (analyticAt_clog m).comp_analyticWithinAt fa + /-- `log` is analytic away from nonpositive reals -/ +theorem AnalyticOnNhd.clog (fs : AnalyticOnNhd ℂ f s) (m : ∀ z ∈ s, f z ∈ slitPlane) : + AnalyticOnNhd ℂ (fun z ↦ log (f z)) s := + fun z n ↦ (analyticAt_clog (m z n)).comp (fs z n) + theorem AnalyticOn.clog (fs : AnalyticOn ℂ f s) (m : ∀ z ∈ s, f z ∈ slitPlane) : AnalyticOn ℂ (fun z ↦ log (f z)) s := - fun z n ↦ (analyticAt_clog (m z n)).comp (fs z n) + fun z n ↦ (analyticAt_clog (m z n)).analyticWithinAt.comp (fs z n) m /-- `f z ^ g z` is analytic if `f z` is not a nonpositive real -/ -theorem AnalyticAt.cpow (fa : AnalyticAt ℂ f x) (ga : AnalyticAt ℂ g x) - (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ f z ^ g z) x := by - have e : (fun z ↦ f z ^ g z) =ᶠ[𝓝 x] fun z ↦ exp (log (f z) * g z) := by - filter_upwards [(fa.continuousAt.eventually_ne (slitPlane_ne_zero m))] +theorem AnalyticWithinAt.cpow (fa : AnalyticWithinAt ℂ f s x) (ga : AnalyticWithinAt ℂ g s x) + (m : f x ∈ slitPlane) : AnalyticWithinAt ℂ (fun z ↦ f z ^ g z) s x := by + have e : (fun z ↦ f z ^ g z) =ᶠ[𝓝[insert x s] x] fun z ↦ exp (log (f z) * g z) := by + filter_upwards [(fa.continuousWithinAt_insert.eventually_ne (slitPlane_ne_zero m))] intro z fz simp only [fz, cpow_def, if_false] - rw [analyticAt_congr e] + apply AnalyticWithinAt.congr_of_eventuallyEq_insert _ e exact ((fa.clog m).mul ga).cexp +/-- `f z ^ g z` is analytic if `f z` is not a nonpositive real -/ +theorem AnalyticAt.cpow (fa : AnalyticAt ℂ f x) (ga : AnalyticAt ℂ g x) + (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ f z ^ g z) x := by + rw [← analyticWithinAt_univ] at fa ga ⊢ + exact fa.cpow ga m + +/-- `f z ^ g z` is analytic if `f z` avoids nonpositive reals -/ +theorem AnalyticOnNhd.cpow (fs : AnalyticOnNhd ℂ f s) (gs : AnalyticOnNhd ℂ g s) + (m : ∀ z ∈ s, f z ∈ slitPlane) : AnalyticOnNhd ℂ (fun z ↦ f z ^ g z) s := + fun z n ↦ (fs z n).cpow (gs z n) (m z n) + /-- `f z ^ g z` is analytic if `f z` avoids nonpositive reals -/ theorem AnalyticOn.cpow (fs : AnalyticOn ℂ f s) (gs : AnalyticOn ℂ g s) (m : ∀ z ∈ s, f z ∈ slitPlane) : AnalyticOn ℂ (fun z ↦ f z ^ g z) s := diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean index 8f72e2ec290e0..4d4cee818d69d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean @@ -547,13 +547,13 @@ theorem Gamma_mul_Gamma_add_half (s : ℂ) : convert congr_arg Inv.inv (congr_fun this s) using 1 · rw [mul_inv, inv_inv, inv_inv] · rw [div_eq_mul_inv, mul_inv, mul_inv, inv_inv, inv_inv, ← cpow_neg, neg_sub] - have h1 : AnalyticOn ℂ (fun z : ℂ => (Gamma z)⁻¹ * (Gamma (z + 1 / 2))⁻¹) univ := by - refine DifferentiableOn.analyticOn ?_ isOpen_univ + have h1 : AnalyticOnNhd ℂ (fun z : ℂ => (Gamma z)⁻¹ * (Gamma (z + 1 / 2))⁻¹) univ := by + refine DifferentiableOn.analyticOnNhd ?_ isOpen_univ refine (differentiable_one_div_Gamma.mul ?_).differentiableOn exact differentiable_one_div_Gamma.comp (differentiable_id.add (differentiable_const _)) - have h2 : AnalyticOn ℂ + have h2 : AnalyticOnNhd ℂ (fun z => (Gamma (2 * z))⁻¹ * (2 : ℂ) ^ (2 * z - 1) / ↑(√π)) univ := by - refine DifferentiableOn.analyticOn ?_ isOpen_univ + refine DifferentiableOn.analyticOnNhd ?_ isOpen_univ refine (Differentiable.mul ?_ (differentiable_const _)).differentiableOn apply Differentiable.mul · exact differentiable_one_div_Gamma.comp (differentiable_id'.const_mul _) @@ -563,7 +563,7 @@ theorem Gamma_mul_Gamma_add_half (s : ℂ) : rw [tendsto_nhdsWithin_iff]; constructor · exact tendsto_nhdsWithin_of_tendsto_nhds continuous_ofReal.continuousAt · exact eventually_nhdsWithin_iff.mpr (Eventually.of_forall fun t ht => ofReal_ne_one.mpr ht) - refine AnalyticOn.eq_of_frequently_eq h1 h2 (h3.frequently ?_) + refine AnalyticOnNhd.eq_of_frequently_eq h1 h2 (h3.frequently ?_) refine ((Eventually.filter_mono nhdsWithin_le_nhds) ?_).frequently refine (eventually_gt_nhds zero_lt_one).mp (Eventually.of_forall fun t ht => ?_) rw [← mul_inv, Gamma_ofReal, (by norm_num : (t : ℂ) + 1 / 2 = ↑(t + 1 / 2)), Gamma_ofReal, ← diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index 442b24423f19a..8ef606a4540a1 100644 --- a/Mathlib/Geometry/Manifold/AnalyticManifold.lean +++ b/Mathlib/Geometry/Manifold/AnalyticManifold.lean @@ -17,7 +17,7 @@ interior and smooth everywhere (including at the boundary). The definition mirr analytic manifolds are smooth manifolds. Completeness is required throughout, but this is nonessential: it is due to many of the lemmas about -AnalyticWithinOn` requiring completeness for ease of proof. +AnalyticOn` requiring completeness for ease of proof. -/ noncomputable section @@ -42,10 +42,10 @@ analytic on the interior, and map the interior to itself. This allows us to def section analyticGroupoid /-- Given a model with corners `(E, H)`, we define the pregroupoid of analytic transformations of -`H` as the maps that are `AnalyticWithinOn` when read in `E` through `I`. Using `AnalyticWithinOn` -rather than `AnalyticOn` gives us meaningful definitions at boundary points. -/ +`H` as the maps that are `AnalyticOn` when read in `E` through `I`. Using `AnalyticOn` +rather than `AnalyticOnNhd` gives us meaningful definitions at boundary points. -/ def analyticPregroupoid : Pregroupoid H where - property f s := AnalyticWithinOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) + property f s := AnalyticOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) comp {f g u v} hf hg _ _ _ := by have : I ∘ (g ∘ f) ∘ I.symm = (I ∘ g ∘ I.symm) ∘ I ∘ f ∘ I.symm := by ext x; simp simp only [this] @@ -54,12 +54,12 @@ def analyticPregroupoid : Pregroupoid H where · rintro x ⟨hx1, _⟩ simpa only [mfld_simps] using hx1.2 id_mem := by - apply analyticWithinOn_id.congr + apply analyticOn_id.congr rintro x ⟨_, hx2⟩ obtain ⟨y, hy⟩ := mem_range.1 hx2 simp only [mfld_simps, ← hy] locality {f u} _ H := by - apply analyticWithinOn_of_locally_analyticWithinOn + apply analyticOn_of_locally_analyticOn rintro y ⟨hy1, hy2⟩ obtain ⟨x, hx⟩ := mem_range.1 hy2 simp only [mfld_simps, ← hx] at hy1 ⊢ @@ -75,8 +75,8 @@ def analyticPregroupoid : Pregroupoid H where rw [fg _ hy1] /-- Given a model with corners `(E, H)`, we define the groupoid of analytic transformations of -`H` as the maps that are `AnalyticWithinOn` when read in `E` through `I`. Using `AnalyticWithinOn` -rather than `AnalyticOn` gives us meaningful definitions at boundary points. -/ +`H` as the maps that are `AnalyticOn` when read in `E` through `I`. Using `AnalyticOn` +rather than `AnalyticOnNhd` gives us meaningful definitions at boundary points. -/ def analyticGroupoid : StructureGroupoid H := (analyticPregroupoid I).groupoid @@ -84,9 +84,9 @@ def analyticGroupoid : StructureGroupoid H := theorem ofSet_mem_analyticGroupoid {s : Set H} (hs : IsOpen s) : PartialHomeomorph.ofSet s hs ∈ analyticGroupoid I := by rw [analyticGroupoid, mem_groupoid_of_pregroupoid] - suffices h : AnalyticWithinOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ range I) by + suffices h : AnalyticOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ range I) by simp [h, analyticPregroupoid] - have hi : AnalyticWithinOn 𝕜 id (univ : Set E) := analyticWithinOn_id + have hi : AnalyticOn 𝕜 id (univ : Set E) := analyticOn_id exact (hi.mono (subset_univ _)).congr (fun x hx ↦ I.right_inv hx.2) /-- The composition of a partial homeomorphism from `H` to `M` and its inverse belongs to @@ -108,17 +108,17 @@ instance : ClosedUnderRestriction (analyticGroupoid I) := /-- `f ∈ analyticGroupoid` iff it and its inverse are analytic within `range I`. -/ lemma mem_analyticGroupoid {I : ModelWithCorners 𝕜 E H} {f : PartialHomeomorph H H} : f ∈ analyticGroupoid I ↔ - AnalyticWithinOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' f.source ∩ range I) ∧ - AnalyticWithinOn 𝕜 (I ∘ f.symm ∘ I.symm) (I.symm ⁻¹' f.target ∩ range I) := by + AnalyticOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' f.source ∩ range I) ∧ + AnalyticOn 𝕜 (I ∘ f.symm ∘ I.symm) (I.symm ⁻¹' f.target ∩ range I) := by rfl /-- The analytic groupoid on a boundaryless charted space modeled on a complete vector space consists of the partial homeomorphisms which are analytic and have analytic inverse. -/ theorem mem_analyticGroupoid_of_boundaryless [I.Boundaryless] (e : PartialHomeomorph H H) : - e ∈ analyticGroupoid I ↔ AnalyticOn 𝕜 (I ∘ e ∘ I.symm) (I '' e.source) ∧ - AnalyticOn 𝕜 (I ∘ e.symm ∘ I.symm) (I '' e.target) := by + e ∈ analyticGroupoid I ↔ AnalyticOnNhd 𝕜 (I ∘ e ∘ I.symm) (I '' e.source) ∧ + AnalyticOnNhd 𝕜 (I ∘ e.symm ∘ I.symm) (I '' e.target) := by simp only [mem_analyticGroupoid, I.range_eq_univ, inter_univ, I.image_eq] - rw [IsOpen.analyticWithinOn_iff_analyticOn, IsOpen.analyticWithinOn_iff_analyticOn] + rw [IsOpen.analyticOn_iff_analyticOnNhd, IsOpen.analyticOn_iff_analyticOnNhd] · exact I.continuous_symm.isOpen_preimage _ e.open_target · exact I.continuous_symm.isOpen_preimage _ e.open_source @@ -131,12 +131,12 @@ theorem analyticGroupoid_prod {E A : Type} [NormedAddCommGroup E] [NormedSpace f.prod g ∈ analyticGroupoid (I.prod J) := by have pe : range (I.prod J) = (range I).prod (range J) := I.range_prod simp only [mem_analyticGroupoid, Function.comp, image_subset_iff] at fa ga ⊢ - exact ⟨AnalyticWithinOn.prod - (fa.1.comp analyticWithinOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) - (ga.1.comp analyticWithinOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩), - AnalyticWithinOn.prod - (fa.2.comp analyticWithinOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) - (ga.2.comp analyticWithinOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩)⟩ + exact ⟨AnalyticOn.prod + (fa.1.comp analyticOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) + (ga.1.comp analyticOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩), + AnalyticOn.prod + (fa.2.comp analyticOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) + (ga.2.comp analyticOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩)⟩ end analyticGroupoid diff --git a/Mathlib/NumberTheory/LSeries/Deriv.lean b/Mathlib/NumberTheory/LSeries/Deriv.lean index d9a355faf2a9f..f8f5726a088aa 100644 --- a/Mathlib/NumberTheory/LSeries/Deriv.lean +++ b/Mathlib/NumberTheory/LSeries/Deriv.lean @@ -20,7 +20,7 @@ import Mathlib.Analysis.Complex.HalfPlane * We prove similar results for iterated derivatives (`LSeries.iteratedDeriv`). * We use this to show that `LSeries f` is holomorphic on the right half-plane of - absolute convergence (`LSeries.analyticOn`). + absolute convergence (`LSeries.analyticOnNhd`). ## Implementation notes @@ -151,6 +151,10 @@ lemma LSeries_differentiableOn (f : ℕ → ℂ) : fun _ hz ↦ (LSeries_hasDerivAt hz).differentiableAt.differentiableWithinAt /-- The L-series of `f` is holomorphic on its open half-plane of absolute convergence. -/ +lemma LSeries_analyticOnNhd (f : ℕ → ℂ) : + AnalyticOnNhd ℂ (LSeries f) {s | abscissaOfAbsConv f < s.re} := + (LSeries_differentiableOn f).analyticOnNhd <| isOpen_re_gt_EReal _ + lemma LSeries_analyticOn (f : ℕ → ℂ) : AnalyticOn ℂ (LSeries f) {s | abscissaOfAbsConv f < s.re} := - (LSeries_differentiableOn f).analyticOn <| isOpen_re_gt_EReal _ + (LSeries_analyticOnNhd f).analyticOn diff --git a/Mathlib/NumberTheory/LSeries/ZMod.lean b/Mathlib/NumberTheory/LSeries/ZMod.lean index 66dbde51f1f55..2ef6c910b132d 100644 --- a/Mathlib/NumberTheory/LSeries/ZMod.lean +++ b/Mathlib/NumberTheory/LSeries/ZMod.lean @@ -177,13 +177,13 @@ lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ let g := expZeta (toAddCircle j) have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [mem_ite_univ_right, U]; tauto -- hypotheses for uniqueness of analytic continuation - have hf : AnalyticOn ℂ f U := by - refine DifferentiableOn.analyticOn (fun u hu ↦ ?_) hUo + have hf : AnalyticOnNhd ℂ f U := by + refine DifferentiableOn.analyticOnNhd (fun u hu ↦ ?_) hUo refine (differentiableAt_LFunction _ _ ((hU.mp hu).imp_right fun h ↦ ?_)).differentiableWithinAt simp only [mul_comm j, AddChar.sum_mulShift _ (isPrimitive_stdAddChar _), h, ↓reduceIte, CharP.cast_eq_zero, or_true] - have hg : AnalyticOn ℂ g U := by - refine DifferentiableOn.analyticOn (fun u hu ↦ ?_) hUo + have hg : AnalyticOnNhd ℂ g U := by + refine DifferentiableOn.analyticOnNhd (fun u hu ↦ ?_) hUo refine (differentiableAt_expZeta _ _ ((hU.mp hu).imp_right fun h ↦ ?_)).differentiableWithinAt rwa [ne_eq, toAddCircle_eq_zero] have hUc : IsPreconnected U := by @@ -451,7 +451,7 @@ Functional equation for completed L-functions (even case), valid at all points o theorem completedLFunction_one_sub_even (hΦ : Φ.Even) (s : ℂ) (hs₀ : s ≠ 0 ∨ ∑ j, Φ j = 0) (hs₁ : s ≠ 1 ∨ Φ 0 = 0) : completedLFunction Φ (1 - s) = N ^ (s - 1) * completedLFunction (𝓕 Φ) s := by - -- We prove this using `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`, so we need to + -- We prove this using `AnalyticOnNhd.eqOn_of_preconnected_of_eventuallyEq`, so we need to -- gather up the ingredients for this big theorem. -- First set up some notations: let F (t) := completedLFunction Φ (1 - t) @@ -477,12 +477,14 @@ theorem completedLFunction_one_sub_even (hΦ : Φ.Even) (s : ℂ) simp [U, Uc, h, h', and_comm] · simp only [rank_real_complex, Nat.one_lt_ofNat] -- Analyticity on U: - have hF : AnalyticOn ℂ F U := by - refine DifferentiableOn.analyticOn (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo + have hF : AnalyticOnNhd ℂ F U := by + refine DifferentiableOn.analyticOnNhd + (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo refine (differentiableAt_completedLFunction Φ _ ?_ ?_).comp t (differentiableAt_id.const_sub 1) exacts [ht.2.imp_left (sub_ne_zero.mpr ∘ Ne.symm), ht.1.imp_left sub_eq_self.not.mpr] - have hG : AnalyticOn ℂ G U := by - refine DifferentiableOn.analyticOn (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo + have hG : AnalyticOnNhd ℂ G U := by + refine DifferentiableOn.analyticOnNhd + (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo apply ((differentiableAt_id.sub_const 1).const_cpow (.inl (NeZero.ne _))).mul apply differentiableAt_completedLFunction _ _ (ht.1.imp_right fun h ↦ dft_apply_zero Φ ▸ h) exact ht.2.imp_right (fun h ↦ by simp only [← dft_apply_zero, dft_dft, neg_zero, h, smul_zero]) @@ -512,7 +514,7 @@ theorem completedLFunction_one_sub_odd (hΦ : Φ.Odd) (s : ℂ) : have hFG : F =ᶠ[𝓝 2] G := by filter_upwards [this] with t ht using completedLFunction_one_sub_of_one_lt_odd hΦ ht -- now apply the big hammer to finish - rw [← analyticOn_univ_iff_differentiable] at hF hG + rw [← analyticOnNhd_univ_iff_differentiable] at hF hG exact congr_fun (hF.eq_of_eventuallyEq hG hFG) s end signed diff --git a/docs/overview.yaml b/docs/overview.yaml index be28612dbf810..e1d21817d53b5 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -352,7 +352,7 @@ Analysis: Liouville theorem: 'Differentiable.apply_eq_apply_of_bounded' maximum modulus principle: 'Complex.eventually_eq_of_isLocalMax_norm' principle of isolated zeros: 'AnalyticAt.eventually_eq_zero_or_eventually_ne_zero' - principle of analytic continuation: 'AnalyticOn.eqOn_of_preconnected_of_frequently_eq' + principle of analytic continuation: 'AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq' analyticity of holomorphic functions: 'DifferentiableOn.analyticAt' Schwarz lemma: 'Complex.abs_le_abs_of_mapsTo_ball_self' removable singularity: 'Complex.differentiableOn_update_limUnder_insert_of_isLittleO' diff --git a/docs/undergrad.yaml b/docs/undergrad.yaml index 21619980559e5..f1113456868a1 100644 --- a/docs/undergrad.yaml +++ b/docs/undergrad.yaml @@ -387,7 +387,7 @@ Single Variable Complex Analysis: Cauchy formulas: 'Complex.two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable' analyticity of a holomorphic function: 'DifferentiableOn.analyticAt' principle of isolated zeros: 'AnalyticAt.eventually_eq_zero_or_eventually_ne_zero' - principle of analytic continuation: 'AnalyticOn.eqOn_of_preconnected_of_frequently_eq' + principle of analytic continuation: 'AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq' maximum principle: 'Complex.eventually_eq_of_isLocalMax_norm' isolated singularities: '' Laurent series: '' diff --git a/scripts/no_lints_prime_decls.txt b/scripts/no_lints_prime_decls.txt index 048a285c74a49..5a3fa4e0c5ec5 100644 --- a/scripts/no_lints_prime_decls.txt +++ b/scripts/no_lints_prime_decls.txt @@ -162,10 +162,10 @@ AlgHom.coe_restrictScalars' AlgHom.toAddMonoidHom' AlgHom.toMonoidHom' AlternatingMap.domCoprod.summand_mk'' -analyticOn_congr' -AnalyticOn.congr' -AnalyticOn.eval_continuousLinearMap' -AnalyticOn.eval_linearMap' +analyticOnNhd_congr' +AnalyticOnNhd.congr' +AnalyticOnNhd.eval_continuousLinearMap' +AnalyticOnNhd.eval_linearMap' AntilipschitzWith.le_mul_nnnorm' AntilipschitzWith.le_mul_norm' AntilipschitzWith.to_rightInvOn' From d942826fbe921454e3ae9942d00b06526e310812 Mon Sep 17 00:00:00 2001 From: FR Date: Thu, 26 Sep 2024 11:05:07 +0000 Subject: [PATCH 165/170] chore(SetTheory/Game/PGame): rename (#17120) --- Mathlib/SetTheory/Game/Basic.lean | 4 ++-- Mathlib/SetTheory/Game/PGame.lean | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index f6b0a8b89caf6..8c72765907e52 100644 --- a/Mathlib/SetTheory/Game/Basic.lean +++ b/Mathlib/SetTheory/Game/Basic.lean @@ -238,7 +238,7 @@ theorem quot_natCast : ∀ n : ℕ, ⟦(n : PGame)⟧ = (n : Game) theorem quot_eq_of_mk'_quot_eq {x y : PGame} (L : x.LeftMoves ≃ y.LeftMoves) (R : x.RightMoves ≃ y.RightMoves) (hl : ∀ i, (⟦x.moveLeft i⟧ : Game) = ⟦y.moveLeft (L i)⟧) (hr : ∀ j, (⟦x.moveRight j⟧ : Game) = ⟦y.moveRight (R j)⟧) : (⟦x⟧ : Game) = ⟦y⟧ := - game_eq (equiv_of_mk_equiv L R (fun _ => equiv_iff_game_eq.2 (hl _)) + game_eq (.of_equiv L R (fun _ => equiv_iff_game_eq.2 (hl _)) (fun _ => equiv_iff_game_eq.2 (hr _))) /-! Multiplicative operations can be defined at the level of pre-games, @@ -605,7 +605,7 @@ def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x (try rintro (⟨i, ⟨⟩⟩ | ⟨i, ⟨⟩⟩)) <;> { dsimp apply (Relabelling.subCongr (Relabelling.refl _) (mulZeroRelabelling _)).trans - rw [sub_zero] + rw [sub_zero_eq_add_zero] exact (addZeroRelabelling _).trans <| (((mulOneRelabelling _).addCongr (mulZeroRelabelling _)).trans <| addZeroRelabelling _) } diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 94f9ebf8cd866..55a01998f3b98 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -822,13 +822,15 @@ theorem equiv_congr_right {x₁ x₂ : PGame} : (x₁ ≈ x₂) ↔ ∀ y₁, (x ⟨fun h _ => ⟨fun h' => Equiv.trans (Equiv.symm h) h', fun h' => Equiv.trans h h'⟩, fun h => (h x₂).2 <| equiv_rfl⟩ -theorem equiv_of_mk_equiv {x y : PGame} (L : x.LeftMoves ≃ y.LeftMoves) +theorem Equiv.of_equiv {x y : PGame} (L : x.LeftMoves ≃ y.LeftMoves) (R : x.RightMoves ≃ y.RightMoves) (hl : ∀ i, x.moveLeft i ≈ y.moveLeft (L i)) (hr : ∀ j, x.moveRight j ≈ y.moveRight (R j)) : x ≈ y := by constructor <;> rw [le_def] · exact ⟨fun i => Or.inl ⟨_, (hl i).1⟩, fun j => Or.inr ⟨_, by simpa using (hr (R.symm j)).1⟩⟩ · exact ⟨fun i => Or.inl ⟨_, by simpa using (hl (L.symm i)).2⟩, fun j => Or.inr ⟨_, (hr j).2⟩⟩ +@[deprecated (since := "2024-09-26")] alias equiv_of_mk_equiv := Equiv.of_equiv + /-- The fuzzy, confused, or incomparable relation on pre-games. If `x ‖ 0`, then the first player can always win `x`. -/ @@ -1432,9 +1434,11 @@ instance : Sub PGame := ⟨fun x y => x + -y⟩ @[simp] -theorem sub_zero (x : PGame) : x - 0 = x + 0 := +theorem sub_zero_eq_add_zero (x : PGame) : x - 0 = x + 0 := show x + -0 = x + 0 by rw [neg_zero] +@[deprecated (since := "2024-09-26")] alias sub_zero := sub_zero_eq_add_zero + /-- If `w` has the same moves as `x` and `y` has the same moves as `z`, then `w - y` has the same moves as `x - z`. -/ def Relabelling.subCongr {w x y z : PGame} (h₁ : w ≡r x) (h₂ : y ≡r z) : w - y ≡r x - z := From a60d315e0ec15d6a373325b2e60e80b8638384dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 26 Sep 2024 12:28:31 +0000 Subject: [PATCH 166/170] feat: the (covariant) long exact sequence of Ext (#14515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We obtain the long exact sequence of `Ext`-groups `Ext X S.X₁ n₀ → Ext X S.X₂ n₀ → Ext X S.X₃ n₀ → Ext X S.X₁ n₁ → Ext X S.X₂ n₁ → Ext X S.X₃ n₁` when `n₀ + 1 = n₁` and `S` is a short exact short complex in an abelian category. Co-authored-by: dagurtomas Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + .../Homology/DerivedCategory/Ext/Basic.lean | 1 - .../DerivedCategory/Ext/ExactSequences.lean | 164 ++++++++++++++++++ .../DerivedCategory/Ext/ExtClass.lean | 2 + Mathlib/Algebra/Homology/ShortComplex/Ab.lean | 12 ++ 5 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean diff --git a/Mathlib.lean b/Mathlib.lean index 8f564f4f1e5de..f20337943c919 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -345,6 +345,7 @@ import Mathlib.Algebra.Homology.ConcreteCategory import Mathlib.Algebra.Homology.DerivedCategory.Basic import Mathlib.Algebra.Homology.DerivedCategory.ExactFunctor import Mathlib.Algebra.Homology.DerivedCategory.Ext.Basic +import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExactSequences import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExtClass import Mathlib.Algebra.Homology.DerivedCategory.HomologySequence import Mathlib.Algebra.Homology.DerivedCategory.ShortExact diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean index 781e2de9cf31f..774df032bb48c 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean @@ -36,7 +36,6 @@ sheaves over `X` shall be in `Type u`. ## TODO * compute `Ext X Y 0` -* construct the covariant long exact sequences of `Ext`. * construct the contravariant long exact sequences of `Ext`. -/ diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean new file mode 100644 index 0000000000000..427dd7ae80159 --- /dev/null +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2024 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.Algebra.Exact +import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExtClass +import Mathlib.Algebra.Homology.ShortComplex.Ab +import Mathlib.CategoryTheory.Triangulated.Yoneda + +/-! +# Long exact sequences of `Ext`-groups + +In this file, we obtain the covariant long exact sequence of `Ext`: +`Ext X S.X₁ n₀ → Ext X S.X₂ n₀ → Ext X S.X₃ n₀ → Ext X S.X₁ n₁ → Ext X S.X₂ n₁ → Ext X S.X₃ n₁` +when `S` is a short exact short complex in an abelian category `C`, `n₀ + 1 = n₁` and `X : C`. + +-/ + +universe w' w v u + +namespace CategoryTheory + +open Opposite DerivedCategory + +variable {C : Type u} [Category.{v} C] [Abelian C] [HasExt.{w} C] + +namespace Abelian + +namespace Ext + +section CovariantSequence + +lemma hom_comp_singleFunctor_map_shift [HasDerivedCategory.{w'} C] + {X Y Z : C} {n : ℕ} (x : Ext X Y n) (f : Y ⟶ Z) : + x.hom ≫ ((DerivedCategory.singleFunctor C 0).map f)⟦(n : ℤ)⟧' = + (x.comp (mk₀ f) (add_zero n)).hom := by + simp only [comp_hom, mk₀_hom, ShiftedHom.comp_mk₀] + +variable {X : C} {S : ShortComplex C} (hS : S.ShortExact) + +lemma preadditiveCoyoneda_homologySequenceδ_singleTriangle_apply + [HasDerivedCategory.{w'} C] {X : C} {n₀ : ℕ} (x : Ext X S.X₃ n₀) + {n₁ : ℕ} (h : n₀ + 1 = n₁) : + (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequenceδ + hS.singleTriangle n₀ n₁ (by omega) x.hom = + (x.comp hS.extClass h).hom := by + rw [Pretriangulated.preadditiveCoyoneda_homologySequenceδ_apply, + comp_hom, hS.extClass_hom, ShiftedHom.comp] + rfl + +variable (X) + +include hS in +/-- Alternative formulation of `covariant_sequence_exact₂` -/ +lemma covariant_sequence_exact₂' (n : ℕ) : + (ShortComplex.mk (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n))) + (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n))) (by + ext x + dsimp [AddCommGrp.ofHom] + simp only [comp_assoc_of_third_deg_zero, mk₀_comp_mk₀, ShortComplex.zero, mk₀_zero, + comp_zero] + rfl)).Exact := by + letI := HasDerivedCategory.standard C + have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₂ _ + (hS.singleTriangle_distinguished) n + rw [ShortComplex.ab_exact_iff_function_exact] at this ⊢ + apply Function.Exact.of_ladder_addEquiv_of_exact' (e₁ := Ext.homAddEquiv) + (e₂ := Ext.homAddEquiv) (e₃ := Ext.homAddEquiv) (H := this) + all_goals ext x; apply hom_comp_singleFunctor_map_shift (C := C) + +section + +variable (n₀ n₁ : ℕ) (h : n₀ + 1 = n₁) + +/-- Alternative formulation of `covariant_sequence_exact₃` -/ +lemma covariant_sequence_exact₃' : + (ShortComplex.mk (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n₀))) + (AddCommGrp.ofHom (hS.extClass.postcomp X h)) (by + ext x + dsimp [AddCommGrp.ofHom] + simp only [comp_assoc_of_second_deg_zero, ShortComplex.ShortExact.comp_extClass, + comp_zero] + rfl)).Exact := by + letI := HasDerivedCategory.standard C + have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₃ _ + (hS.singleTriangle_distinguished) n₀ n₁ (by omega) + rw [ShortComplex.ab_exact_iff_function_exact] at this ⊢ + apply Function.Exact.of_ladder_addEquiv_of_exact' (e₁ := Ext.homAddEquiv) + (e₂ := Ext.homAddEquiv) (e₃ := Ext.homAddEquiv) (H := this) + · ext x; apply hom_comp_singleFunctor_map_shift (C := C) + · ext x + exact preadditiveCoyoneda_homologySequenceδ_singleTriangle_apply hS x h + +/-- Alternative formulation of `covariant_sequence_exact₁` -/ +lemma covariant_sequence_exact₁' : + (ShortComplex.mk + (AddCommGrp.ofHom (hS.extClass.postcomp X h)) + (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n₁))) (by + ext x + dsimp [AddCommGrp.ofHom] + simp only [comp_assoc_of_third_deg_zero, ShortComplex.ShortExact.extClass_comp, comp_zero] + rfl)).Exact := by + letI := HasDerivedCategory.standard C + have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₁ _ + (hS.singleTriangle_distinguished) n₀ n₁ (by omega) + rw [ShortComplex.ab_exact_iff_function_exact] at this ⊢ + apply Function.Exact.of_ladder_addEquiv_of_exact' (e₁ := Ext.homAddEquiv) + (e₂ := Ext.homAddEquiv) (e₃ := Ext.homAddEquiv) (H := this) + · ext x + exact preadditiveCoyoneda_homologySequenceδ_singleTriangle_apply hS x h + · ext x; apply hom_comp_singleFunctor_map_shift (C := C) + +open ComposableArrows + +/-- Given a short exact short complex `S` in an abelian category `C` and an object `X : C`, +this is the long exact sequence +`Ext X S.X₁ n₀ → Ext X S.X₂ n₀ → Ext X S.X₃ n₀ → Ext X S.X₁ n₁ → Ext X S.X₂ n₁ → Ext X S.X₃ n₁` +when `n₀ + 1 = n₁` -/ +noncomputable def covariantSequence : ComposableArrows AddCommGrp.{w} 5 := + mk₅ (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n₀))) + (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n₀))) + (AddCommGrp.ofHom (hS.extClass.postcomp X h)) + (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n₁))) + (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n₁))) + +lemma covariantSequence_exact : + (covariantSequence X hS n₀ n₁ h).Exact := + exact_of_δ₀ (covariant_sequence_exact₂' X hS n₀).exact_toComposableArrows + (exact_of_δ₀ (covariant_sequence_exact₃' X hS n₀ n₁ h).exact_toComposableArrows + (exact_of_δ₀ (covariant_sequence_exact₁' X hS n₀ n₁ h).exact_toComposableArrows + (covariant_sequence_exact₂' X hS n₁).exact_toComposableArrows)) + +end + +lemma covariant_sequence_exact₁ {n₁ : ℕ} (x₁ : Ext X S.X₁ n₁) + (hx₁ : x₁.comp (mk₀ S.f) (add_zero n₁) = 0) {n₀ : ℕ} (hn₀ : n₀ + 1 = n₁) : + ∃ (x₃ : Ext X S.X₃ n₀), x₃.comp hS.extClass hn₀ = x₁ := by + have := covariant_sequence_exact₁' X hS n₀ n₁ hn₀ + rw [ShortComplex.ab_exact_iff] at this + exact this x₁ hx₁ + +include hS in +lemma covariant_sequence_exact₂ {n : ℕ} (x₂ : Ext X S.X₂ n) + (hx₂ : x₂.comp (mk₀ S.g) (add_zero n) = 0) : + ∃ (x₁ : Ext X S.X₁ n), x₁.comp (mk₀ S.f) (add_zero n) = x₂ := by + have := covariant_sequence_exact₂' X hS n + rw [ShortComplex.ab_exact_iff] at this + exact this x₂ hx₂ + +lemma covariant_sequence_exact₃ {n₀ : ℕ} (x₃ : Ext X S.X₃ n₀) {n₁ : ℕ} (hn₁ : n₀ + 1 = n₁) + (hx₃ : x₃.comp hS.extClass hn₁ = 0) : + ∃ (x₂ : Ext X S.X₂ n₀), x₂.comp (mk₀ S.g) (add_zero n₀) = x₃ := by + have := covariant_sequence_exact₃' X hS n₀ n₁ hn₁ + rw [ShortComplex.ab_exact_iff] at this + exact this x₃ hx₃ + +end CovariantSequence + +end Ext + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean index 9a636124ff714..2869c7955e0c0 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean @@ -29,6 +29,8 @@ namespace ShortComplex variable (S : ShortComplex C) +lemma ext_mk₀_f_comp_ext_mk₀_g : (Ext.mk₀ S.f).comp (Ext.mk₀ S.g) (zero_add 0) = 0 := by simp + namespace ShortExact variable {S} diff --git a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean index 8b76e44a2ca8c..474f801a48272 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean @@ -109,6 +109,18 @@ lemma ab_exact_iff : obtain ⟨x₁, rfl⟩ := h x₂ hx₂ exact ⟨x₁, rfl⟩ +lemma ab_exact_iff_function_exact : + S.Exact ↔ Function.Exact S.f S.g := by + rw [S.ab_exact_iff] + apply forall_congr' + intro x₂ + constructor + · intro h + refine ⟨h, ?_⟩ + rintro ⟨x₁, rfl⟩ + simp only [ab_zero_apply] + · tauto + lemma ab_exact_iff_ker_le_range : S.Exact ↔ S.g.ker ≤ S.f.range := S.ab_exact_iff lemma ab_exact_iff_range_eq_ker : S.Exact ↔ S.f.range = S.g.ker := by From bcb7eb27d429df57287435122b7be30fcbc52862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20G=2E=20Dorais?= Date: Thu, 26 Sep 2024 12:41:25 +0000 Subject: [PATCH 167/170] chore: remove List.ofFn lemmas moved to Batteries (#17159) Co-authored-by: Matthew Ballard --- Mathlib/Analysis/Analytic/Composition.lean | 2 +- Mathlib/Data/List/FinRange.lean | 2 +- Mathlib/Data/List/OfFn.lean | 37 +--------------------- lake-manifest.json | 2 +- 4 files changed, 4 insertions(+), 39 deletions(-) diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index 8b33f213f757e..08f88f4cedb1f 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -1158,7 +1158,7 @@ def sigmaEquivSigmaPi (n : ℕ) : · intro i dsimp [Composition.sigmaCompositionAux] rw [getElem_of_eq (splitWrtComposition_join _ _ _)] - · simp only [getElem_ofFn] + · simp only [List.getElem_ofFn] · simp only [map_ofFn] rfl · congr diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index 240012da5d608..62d8122999597 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -42,7 +42,7 @@ theorem finRange_succ (n : ℕ) : theorem ofFn_eq_pmap {n} {f : Fin n → α} : ofFn f = pmap (fun i hi => f ⟨i, hi⟩) (range n) fun _ => mem_range.1 := by rw [pmap_eq_map_attach] - exact ext_getElem (by simp) fun i hi1 hi2 => by simp [getElem_ofFn f i hi1] + exact ext_getElem (by simp) fun i hi1 hi2 => by simp [List.getElem_ofFn f i hi1] theorem ofFn_id (n) : ofFn id = finRange n := ofFn_eq_pmap diff --git a/Mathlib/Data/List/OfFn.lean b/Mathlib/Data/List/OfFn.lean index cdfcb9554f599..9aa74790b948b 100644 --- a/Mathlib/Data/List/OfFn.lean +++ b/Mathlib/Data/List/OfFn.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Batteries.Data.List.OfFn import Batteries.Data.List.Pairwise import Mathlib.Data.Fin.Tuple.Basic @@ -16,7 +17,6 @@ of length `n`. The main statements pertain to lists generated using `List.ofFn` -- `List.length_ofFn`, which tells us the length of such a list - `List.get?_ofFn`, which tells us the nth element of such a list - `List.equivSigmaTuple`, which is an `Equiv` between lists and the functions that generate them via `List.ofFn`. @@ -32,44 +32,9 @@ open Nat namespace List -@[simp] -theorem length_ofFn_go {n} (f : Fin n → α) (i j h) : length (ofFn.go f i j h) = i := by - induction i generalizing j <;> simp_all [ofFn.go] - -/-- The length of a list converted from a function is the size of the domain. -/ -@[simp] -theorem length_ofFn {n} (f : Fin n → α) : length (ofFn f) = n := by - simp [ofFn, length_ofFn_go] - -theorem getElem_ofFn_go {n} (f : Fin n → α) (i j h) (k) (hk : k < (ofFn.go f i j h).length) : - (ofFn.go f i j h)[k] = f ⟨j + k, by simp at hk; omega⟩ := by - let i+1 := i - cases k <;> simp [ofFn.go, getElem_ofFn_go (i := i)] - congr 2; omega - -theorem get_ofFn_go {n} (f : Fin n → α) (i j h) (k) (hk) : - get (ofFn.go f i j h) ⟨k, hk⟩ = f ⟨j + k, by simp at hk; omega⟩ := by - simp [getElem_ofFn_go] - -@[simp] -theorem getElem_ofFn {n} (f : Fin n → α) (i : Nat) (h : i < (ofFn f).length) : - (ofFn f)[i] = f ⟨i, by simp_all⟩ := by - simp [ofFn, getElem_ofFn_go] - theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f (Fin.cast (by simp) i) := by simp; congr -/-- The `n`th element of a list -/ -@[simp] -theorem getElem?_ofFn {n} (f : Fin n → α) (i) : (ofFn f)[i]? = ofFnNthVal f i := - if h : i < (ofFn f).length - then by - rw [getElem?_eq_getElem h, getElem_ofFn] - · simp only [length_ofFn] at h; simp [ofFnNthVal, h] - else by - rw [ofFnNthVal, dif_neg] <;> - simpa using h - /-- The `n`th element of a list -/ theorem get?_ofFn {n} (f : Fin n → α) (i) : get? (ofFn f) i = ofFnNthVal f i := by simp diff --git a/lake-manifest.json b/lake-manifest.json index f82a37b5c0c11..c800c445bdf67 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "c57ab80c8dd20b345b29c81c446c78a6b3677d20", + "rev": "98f2215707ae293a5612217dc29c05b515269512", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 367f25d3750097169f52c46b90f06497586b3a31 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 26 Sep 2024 15:20:40 +0000 Subject: [PATCH 168/170] refactor(CategoryTheory/MorphismProperty): introduce meta properties `RespectsLeft` and `RespectsRight` (#17139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR introduces new meta properties for morphism properties: If `P` and `Q` are morphism properties, then `P.RespectsLeft Q` if `P` respects `Q` on the left, i.e. if `P f` implies `P (i ≫ f)` whenever `i` satisfies `Q`. Analogously, `P.RespectsRight Q` if `P` respects `Q` on the right. Finally, `P.Respects Q` if `P` respects `Q` both on the left and on the right. The current definition of `RespectsIso P` is now an abbreviation for `P.Respects (isomorphisms C)`. Note that `P.Respects P` is equivalent to `StableUnderComposition P`, but the latter definition was not changed. --- .../AlgebraicGeometry/Morphisms/Basic.lean | 4 +- .../Morphisms/ClosedImmersion.lean | 2 +- .../Morphisms/Constructors.lean | 6 +- .../MorphismProperty/Basic.lean | 148 ++++++++++++------ .../MorphismProperty/Composition.lean | 6 +- .../MorphismProperty/Limits.lean | 4 +- .../Triangulated/Subcategory.lean | 18 +-- Mathlib/RingTheory/RingHomProperties.lean | 8 +- 8 files changed, 121 insertions(+), 75 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean index 7d7bc17702e37..9b5b16f7d5f16 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean @@ -326,7 +326,7 @@ theorem respectsIso_mk {P : AffineTargetMorphismProperty} (h₂ : ∀ {X Y Z} (e : Y ≅ Z) (f : X ⟶ Y) [h : IsAffine Y], P f → @P _ _ (f ≫ e.hom) (isAffine_of_isIso e.inv)) : P.toProperty.RespectsIso := by - constructor + apply MorphismProperty.RespectsIso.mk · rintro X Y Z e f ⟨a, h⟩; exact ⟨a, h₁ e f h⟩ · rintro X Y Z e f ⟨a, h⟩; exact ⟨isAffine_of_isIso e.inv, h₂ e f h⟩ @@ -398,7 +398,7 @@ theorem of_targetAffineLocally_of_isPullback instance (P : AffineTargetMorphismProperty) [P.toProperty.RespectsIso] : (targetAffineLocally P).RespectsIso := by - constructor + apply MorphismProperty.RespectsIso.mk · introv H U rw [morphismRestrict_comp, P.cancel_left_of_respectsIso] exact H U diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index 4eedb17248903..e0f201805fa3b 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -84,7 +84,7 @@ instance comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [IsClosedImmersion f] /-- Composition with an isomorphism preserves closed immersions. -/ instance respectsIso : MorphismProperty.RespectsIso @IsClosedImmersion := by - constructor <;> intro X Y Z e f hf <;> infer_instance + apply MorphismProperty.RespectsIso.mk <;> intro X Y Z e f hf <;> infer_instance /-- Given two commutative rings `R S : CommRingCat` and a surjective morphism `f : R ⟶ S`, the induced scheme morphism `specObj S ⟶ specObj R` is a diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean b/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean index 91b9cb9c05db1..878d9b451bd27 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean @@ -251,12 +251,12 @@ variable {P : ∀ {R S : Type u} [CommRing R] [CommRing S], (R →+* S) → Prop /-- If `P` respects isos, then `stalkwise P` respects isos. -/ lemma stalkwise_respectsIso (hP : RingHom.RespectsIso P) : (stalkwise P).RespectsIso where - precomp {X Y Z} e f hf := by + precomp {X Y Z} e (he : IsIso e) f hf := by simp only [stalkwise, Scheme.comp_coeBase, TopCat.coe_comp, Function.comp_apply] intro x rw [Scheme.stalkMap_comp] - exact (RingHom.RespectsIso.cancel_right_isIso hP _ _).mpr <| hf (e.hom.val.base x) - postcomp {X Y Z} e f hf := by + exact (RingHom.RespectsIso.cancel_right_isIso hP _ _).mpr <| hf (e.val.base x) + postcomp {X Y Z} e (he : IsIso e) f hf := by simp only [stalkwise, Scheme.comp_coeBase, TopCat.coe_comp, Function.comp_apply] intro x rw [Scheme.stalkMap_comp] diff --git a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean index ffeef6490f80e..e9d8b8fb9c0ff 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean @@ -13,8 +13,11 @@ import Mathlib.Order.CompleteBooleanAlgebra We provide the basic framework for talking about properties of morphisms. The following meta-property is defined -* `RespectsIso`: `P` respects isomorphisms if `P f → P (e ≫ f)` and `P f → P (f ≫ e)`, where - `e` is an isomorphism. +* `RespectsLeft P Q`: `P` respects the property `Q` on the left if `P f → P (i ≫ f)` where + `i` satisfies `Q`. +* `RespectsRight P Q`: `P` respects the property `Q` on the right if `P f → P (f ≫ i)` where + `i` satisfies `Q`. +* `Respects`: `P` respects `Q` if `P` respects `Q` both on the left and on the right. -/ @@ -93,22 +96,79 @@ lemma monotone_map (F : C ⥤ D) : intro P Q h X Y f ⟨X', Y', f', hf', ⟨e⟩⟩ exact ⟨X', Y', f', h _ hf', ⟨e⟩⟩ -/-- A morphism property `RespectsIso` if it still holds when composed with an isomorphism -/ -class RespectsIso (P : MorphismProperty C) : Prop where - precomp {X Y Z} (e : X ≅ Y) (f : Y ⟶ Z) (hf : P f) : P (e.hom ≫ f) - postcomp {X Y Z} (e : Y ≅ Z) (f : X ⟶ Y) (hf : P f) : P (f ≫ e.hom) +/-- A morphism property `P` satisfies `P.RespectsRight Q` if it is stable under post-composition +with morphisms satisfying `Q`, i.e. whenever `P` holds for `f` and `Q` holds for `i` then `P` +holds for `f ≫ i`. -/ +class RespectsRight (P Q : MorphismProperty C) : Prop where + postcomp {X Y Z : C} (i : Y ⟶ Z) (hi : Q i) (f : X ⟶ Y) (hf : P f) : P (f ≫ i) -instance RespectsIso.op (P : MorphismProperty C) [h : RespectsIso P] : RespectsIso P.op := - ⟨fun e f hf => h.2 e.unop f.unop hf, fun e f hf => h.1 e.unop f.unop hf⟩ +/-- A morphism property `P` satisfies `P.RespectsLeft Q` if it is stable under +pre-composition with morphisms satisfying `Q`, i.e. whenever `P` holds for `f` +and `Q` holds for `i` then `P` holds for `i ≫ f`. -/ +class RespectsLeft (P Q : MorphismProperty C) : Prop where + precomp {X Y Z : C} (i : X ⟶ Y) (hi : Q i) (f : Y ⟶ Z) (hf : P f) : P (i ≫ f) -instance RespectsIso.unop (P : MorphismProperty Cᵒᵖ) [h : RespectsIso P] : RespectsIso P.unop := - ⟨fun e f hf => h.2 e.op f.op hf, fun e f hf => h.1 e.op f.op hf⟩ +/-- A morphism property `P` satisfies `P.Respects Q` if it is stable under composition on the +left and right by morphisms satisfying `Q`. -/ +class Respects (P Q : MorphismProperty C) extends P.RespectsLeft Q, P.RespectsRight Q : Prop where -/-- The intersection of two isomorphism respecting morphism properties respects isomorphisms. -/ -instance RespectsIso.inf (P Q : MorphismProperty C) [RespectsIso P] [RespectsIso Q] : - RespectsIso (P ⊓ Q) where - precomp e f hf := ⟨RespectsIso.precomp e f hf.left, RespectsIso.precomp e f hf.right⟩ - postcomp e f hf := ⟨RespectsIso.postcomp e f hf.left, RespectsIso.postcomp e f hf.right⟩ +instance (P Q : MorphismProperty C) [P.RespectsLeft Q] [P.RespectsRight Q] : P.Respects Q where + +instance (P Q : MorphismProperty C) [P.RespectsLeft Q] : P.op.RespectsRight Q.op where + postcomp i hi f hf := RespectsLeft.precomp (Q := Q) i.unop hi f.unop hf + +instance (P Q : MorphismProperty C) [P.RespectsRight Q] : P.op.RespectsLeft Q.op where + precomp i hi f hf := RespectsRight.postcomp (Q := Q) i.unop hi f.unop hf + +instance RespectsLeft.inf (P₁ P₂ Q : MorphismProperty C) [P₁.RespectsLeft Q] + [P₂.RespectsLeft Q] : (P₁ ⊓ P₂).RespectsLeft Q where + precomp i hi f hf := ⟨precomp i hi f hf.left, precomp i hi f hf.right⟩ + +instance RespectsRight.inf (P₁ P₂ Q : MorphismProperty C) [P₁.RespectsRight Q] + [P₂.RespectsRight Q] : (P₁ ⊓ P₂).RespectsRight Q where + postcomp i hi f hf := ⟨postcomp i hi f hf.left, postcomp i hi f hf.right⟩ + +variable (C) + +/-- The `MorphismProperty C` satisfied by isomorphisms in `C`. -/ +def isomorphisms : MorphismProperty C := fun _ _ f => IsIso f + +/-- The `MorphismProperty C` satisfied by monomorphisms in `C`. -/ +def monomorphisms : MorphismProperty C := fun _ _ f => Mono f + +/-- The `MorphismProperty C` satisfied by epimorphisms in `C`. -/ +def epimorphisms : MorphismProperty C := fun _ _ f => Epi f + +section + +variable {C} + +/-- `P` respects isomorphisms, if it respects the morphism property `isomorphisms C`, i.e. +it is stable under pre- and postcomposition with isomorphisms. -/ +abbrev RespectsIso (P : MorphismProperty C) : Prop := P.Respects (isomorphisms C) + +lemma RespectsIso.mk (P : MorphismProperty C) + (hprecomp : ∀ {X Y Z : C} (e : X ≅ Y) (f : Y ⟶ Z) (_ : P f), P (e.hom ≫ f)) + (hpostcomp : ∀ {X Y Z : C} (e : Y ≅ Z) (f : X ⟶ Y) (_ : P f), P (f ≫ e.hom)) : + P.RespectsIso where + precomp e (_ : IsIso e) f hf := hprecomp (asIso e) f hf + postcomp e (_ : IsIso e) f hf := hpostcomp (asIso e) f hf + +lemma RespectsIso.precomp (P : MorphismProperty C) [P.RespectsIso] {X Y Z : C} (e : X ⟶ Y) + [IsIso e] (f : Y ⟶ Z) (hf : P f) : P (e ≫ f) := + RespectsLeft.precomp (Q := isomorphisms C) e ‹IsIso e› f hf + +lemma RespectsIso.postcomp (P : MorphismProperty C) [P.RespectsIso] {X Y Z : C} (e : Y ⟶ Z) + [IsIso e] (f : X ⟶ Y) (hf : P f) : P (f ≫ e) := + RespectsRight.postcomp (Q := isomorphisms C) e ‹IsIso e› f hf + +instance RespectsIso.op (P : MorphismProperty C) [h : RespectsIso P] : RespectsIso P.op where + precomp e (_ : IsIso e) f hf := h.postcomp e.unop f.unop hf + postcomp e (_ : IsIso e) f hf := h.precomp e.unop f.unop hf + +instance RespectsIso.unop (P : MorphismProperty Cᵒᵖ) [h : RespectsIso P] : RespectsIso P.unop where + precomp e (_ : IsIso e) f hf := h.postcomp e.op f.op hf + postcomp e (_ : IsIso e) f hf := h.precomp e.op f.op hf /-- The closure by isomorphisms of a `MorphismProperty` -/ def isoClosure (P : MorphismProperty C) : MorphismProperty C := @@ -119,10 +179,10 @@ lemma le_isoClosure (P : MorphismProperty C) : P ≤ P.isoClosure := instance isoClosure_respectsIso (P : MorphismProperty C) : RespectsIso P.isoClosure where - precomp := fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', - ⟨Arrow.isoMk (asIso iso.hom.left ≪≫ e.symm) (asIso iso.hom.right) (by simp)⟩⟩ - postcomp := fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', - ⟨Arrow.isoMk (asIso iso.hom.left) (asIso iso.hom.right ≪≫ e) (by simp)⟩⟩ + precomp := fun e (he : IsIso e) f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', + ⟨Arrow.isoMk (asIso iso.hom.left ≪≫ asIso (inv e)) (asIso iso.hom.right) (by simp)⟩⟩ + postcomp := fun e (he : IsIso e) f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', + ⟨Arrow.isoMk (asIso iso.hom.left) (asIso iso.hom.right ≪≫ asIso e) (by simp)⟩⟩ lemma monotone_isoClosure : Monotone (isoClosure (C := C)) := by intro P Q h X Y f ⟨X', Y', f', hf', ⟨e⟩⟩ @@ -130,11 +190,11 @@ lemma monotone_isoClosure : Monotone (isoClosure (C := C)) := by theorem cancel_left_of_respectsIso (P : MorphismProperty C) [hP : RespectsIso P] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] : P (f ≫ g) ↔ P g := - ⟨fun h => by simpa using hP.1 (asIso f).symm (f ≫ g) h, hP.1 (asIso f) g⟩ + ⟨fun h => by simpa using hP.precomp (inv f) (f ≫ g) h, hP.precomp f g⟩ theorem cancel_right_of_respectsIso (P : MorphismProperty C) [hP : RespectsIso P] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso g] : P (f ≫ g) ↔ P f := - ⟨fun h => by simpa using hP.2 (asIso g).symm (f ≫ g) h, hP.2 (asIso g) f⟩ + ⟨fun h => by simpa using hP.postcomp (inv g) (f ≫ g) h, hP.postcomp g f⟩ theorem arrow_iso_iff (P : MorphismProperty C) [RespectsIso P] {f g : Arrow C} (e : f ≅ g) : P f.hom ↔ P g.hom := by @@ -146,16 +206,13 @@ theorem arrow_mk_iso_iff (P : MorphismProperty C) [RespectsIso P] {W X Y Z : C} P.arrow_iso_iff e theorem RespectsIso.of_respects_arrow_iso (P : MorphismProperty C) - (hP : ∀ (f g : Arrow C) (_ : f ≅ g) (_ : P f.hom), P g.hom) : RespectsIso P := by - constructor - · intro X Y Z e f hf - refine hP (Arrow.mk f) (Arrow.mk (e.hom ≫ f)) (Arrow.isoMk e.symm (Iso.refl _) ?_) hf - dsimp - simp only [Iso.inv_hom_id_assoc, Category.comp_id] - · intro X Y Z e f hf - refine hP (Arrow.mk f) (Arrow.mk (f ≫ e.hom)) (Arrow.isoMk (Iso.refl _) e ?_) hf - dsimp - simp only [Category.id_comp] + (hP : ∀ (f g : Arrow C) (_ : f ≅ g) (_ : P f.hom), P g.hom) : RespectsIso P where + precomp {X Y Z} e (he : IsIso e) f hf := by + refine hP (Arrow.mk f) (Arrow.mk (e ≫ f)) (Arrow.isoMk (asIso (inv e)) (Iso.refl _) ?_) hf + simp + postcomp {X Y Z} e (he : IsIso e) f hf := by + refine hP (Arrow.mk f) (Arrow.mk (f ≫ e)) (Arrow.isoMk (Iso.refl _) (asIso e) ?_) hf + simp lemma isoClosure_eq_iff (P : MorphismProperty C) : P.isoClosure = P ↔ P.RespectsIso := by @@ -227,12 +284,11 @@ lemma map_map (P : MorphismProperty C) (F : C ⥤ D) {E : Type*} [Category E] (G exact map_mem_map _ _ _ (map_mem_map _ _ _ hf) instance RespectsIso.inverseImage (P : MorphismProperty D) [RespectsIso P] (F : C ⥤ D) : - RespectsIso (P.inverseImage F) := by - constructor - all_goals - intro X Y Z e f hf - simpa [MorphismProperty.inverseImage, cancel_left_of_respectsIso, - cancel_right_of_respectsIso] using hf + RespectsIso (P.inverseImage F) where + precomp {X Y Z} e (he : IsIso e) f hf := by + simpa [MorphismProperty.inverseImage, cancel_left_of_respectsIso] using hf + postcomp {X Y Z} e (he : IsIso e) f hf := by + simpa [MorphismProperty.inverseImage, cancel_right_of_respectsIso] using hf lemma map_eq_of_iso (P : MorphismProperty C) {F G : C ⥤ D} (e : F ≅ G) : P.map F = P.map G := by @@ -275,17 +331,7 @@ lemma inverseImage_map_eq_of_isEquivalence erw [((P.map F).inverseImage_equivalence_inverse_eq_map_functor (F.asEquivalence)), map_map, P.map_eq_of_iso F.asEquivalence.unitIso.symm, map_id] - -variable (C) - -/-- The `MorphismProperty C` satisfied by isomorphisms in `C`. -/ -def isomorphisms : MorphismProperty C := fun _ _ f => IsIso f - -/-- The `MorphismProperty C` satisfied by monomorphisms in `C`. -/ -def monomorphisms : MorphismProperty C := fun _ _ f => Mono f - -/-- The `MorphismProperty C` satisfied by epimorphisms in `C`. -/ -def epimorphisms : MorphismProperty C := fun _ _ f => Epi f +end section @@ -313,21 +359,21 @@ theorem epimorphisms.infer_property [hf : Epi f] : (epimorphisms C) f := end instance RespectsIso.monomorphisms : RespectsIso (monomorphisms C) := by - constructor <;> + apply RespectsIso.mk <;> · intro X Y Z e f simp only [monomorphisms.iff] intro apply mono_comp instance RespectsIso.epimorphisms : RespectsIso (epimorphisms C) := by - constructor <;> + apply RespectsIso.mk <;> · intro X Y Z e f simp only [epimorphisms.iff] intro apply epi_comp instance RespectsIso.isomorphisms : RespectsIso (isomorphisms C) := by - constructor <;> + apply RespectsIso.mk <;> · intro X Y Z e f simp only [isomorphisms.iff] intro diff --git a/Mathlib/CategoryTheory/MorphismProperty/Composition.lean b/Mathlib/CategoryTheory/MorphismProperty/Composition.lean index 056a5add8631c..3595312f8c115 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Composition.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Composition.lean @@ -91,9 +91,9 @@ theorem StableUnderInverse.unop {P : MorphismProperty Cᵒᵖ} (h : StableUnderI theorem respectsIso_of_isStableUnderComposition {P : MorphismProperty C} [P.IsStableUnderComposition] (hP : isomorphisms C ≤ P) : - RespectsIso P := - ⟨fun _ _ hf => P.comp_mem _ _ (hP _ (isomorphisms.infer_property _)) hf, - fun _ _ hf => P.comp_mem _ _ hf (hP _ (isomorphisms.infer_property _))⟩ + RespectsIso P := RespectsIso.mk _ + (fun _ _ hf => P.comp_mem _ _ (hP _ (isomorphisms.infer_property _)) hf) + (fun _ _ hf => P.comp_mem _ _ hf (hP _ (isomorphisms.infer_property _))) instance IsStableUnderComposition.inverseImage {P : MorphismProperty D} [P.IsStableUnderComposition] (F : C ⥤ D) : (P.inverseImage F).IsStableUnderComposition where diff --git a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean index e41f911a77318..e3c20a156e317 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean @@ -225,7 +225,7 @@ theorem diagonal_iff {X Y : C} {f : X ⟶ Y} : P.diagonal f ↔ P (pullback.diag Iff.rfl instance RespectsIso.diagonal [P.RespectsIso] : P.diagonal.RespectsIso := by - constructor + apply RespectsIso.mk · introv H rwa [diagonal_iff, pullback.diagonal_comp, P.cancel_left_of_respectsIso, P.cancel_left_of_respectsIso, ← P.cancel_right_of_respectsIso _ @@ -260,7 +260,7 @@ def universally (P : MorphismProperty C) : MorphismProperty C := fun X Y f => ∀ ⦃X' Y' : C⦄ (i₁ : X' ⟶ X) (i₂ : Y' ⟶ Y) (f' : X' ⟶ Y') (_ : IsPullback f' i₁ i₂ f), P f' instance universally_respectsIso (P : MorphismProperty C) : P.universally.RespectsIso := by - constructor + apply RespectsIso.mk · intro X Y Z e f hf X' Z' i₁ i₂ f' H have : IsPullback (𝟙 _) (i₁ ≫ e.hom) i₁ e.inv := IsPullback.of_horiz_isIso diff --git a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean index f4c688ba57647..22baf9e9ef9b8 100644 --- a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean +++ b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean @@ -152,16 +152,16 @@ lemma isoClosure_W : S.isoClosure.W = S.W := by exact ⟨Z, g, h, mem, le_isoClosure _ _ hZ⟩ instance respectsIso_W : S.W.RespectsIso where - precomp := by - rintro X' X Y e f ⟨Z, g, h, mem, mem'⟩ - refine ⟨Z, g, h ≫ e.inv⟦(1 : ℤ)⟧', isomorphic_distinguished _ mem _ ?_, mem'⟩ - refine Triangle.isoMk _ _ e (Iso.refl _) (Iso.refl _) (by aesop_cat) (by aesop_cat) ?_ + precomp {X' X Y} e (he : IsIso e) := by + rintro f ⟨Z, g, h, mem, mem'⟩ + refine ⟨Z, g, h ≫ inv e⟦(1 : ℤ)⟧', isomorphic_distinguished _ mem _ ?_, mem'⟩ + refine Triangle.isoMk _ _ (asIso e) (Iso.refl _) (Iso.refl _) (by aesop_cat) (by aesop_cat) ?_ dsimp - simp only [assoc, ← Functor.map_comp, e.inv_hom_id, Functor.map_id, comp_id, id_comp] - postcomp := by - rintro X Y Y' e f ⟨Z, g, h, mem, mem'⟩ - refine ⟨Z, e.inv ≫ g, h, isomorphic_distinguished _ mem _ ?_, mem'⟩ - exact Triangle.isoMk _ _ (Iso.refl _) e.symm (Iso.refl _) + simp only [Functor.map_inv, assoc, IsIso.inv_hom_id, comp_id, id_comp] + postcomp {X Y Y'} e (he : IsIso e) := by + rintro f ⟨Z, g, h, mem, mem'⟩ + refine ⟨Z, inv e ≫ g, h, isomorphic_distinguished _ mem _ ?_, mem'⟩ + exact Triangle.isoMk _ _ (Iso.refl _) (asIso e).symm (Iso.refl _) instance : S.W.ContainsIdentities := by rw [← isoClosure_W] diff --git a/Mathlib/RingTheory/RingHomProperties.lean b/Mathlib/RingTheory/RingHomProperties.lean index 280f3184fd167..1b12d138c4092 100644 --- a/Mathlib/RingTheory/RingHomProperties.lean +++ b/Mathlib/RingTheory/RingHomProperties.lean @@ -179,15 +179,15 @@ variable {P} lemma toMorphismProperty_respectsIso_iff : RespectsIso P ↔ (toMorphismProperty P).RespectsIso := by - refine ⟨fun h ↦ ⟨?_, ?_⟩, fun h ↦ ⟨?_, ?_⟩⟩ + refine ⟨fun h ↦ MorphismProperty.RespectsIso.mk _ ?_ ?_, fun h ↦ ⟨?_, ?_⟩⟩ · intro X Y Z e f hf exact h.right f e.commRingCatIsoToRingEquiv hf · intro X Y Z e f hf exact h.left f e.commRingCatIsoToRingEquiv hf + · intro X Y Z _ _ _ f e hf + exact h.postcomp e.toCommRingCatIso.hom (CommRingCat.ofHom f) hf · intro X Y Z _ _ _ f e - exact h.postcomp e.toCommRingCatIso (CommRingCat.ofHom f) - · intro X Y Z _ _ _ f e - exact h.precomp e.toCommRingCatIso (CommRingCat.ofHom f) + exact h.precomp e.toCommRingCatIso.hom (CommRingCat.ofHom f) end ToMorphismProperty From d86f6e1c768d3f101574832ac726a4516fe7f4e9 Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:01:03 +0000 Subject: [PATCH 169/170] chore: update Mathlib dependencies 2024-09-26 (#17172) This PR updates the Mathlib dependencies. --- lake-manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lake-manifest.json b/lake-manifest.json index c800c445bdf67..4f9b4a563f31e 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "98f2215707ae293a5612217dc29c05b515269512", + "rev": "40d378f10d013d4ec275bb5d364cce672aa87113", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 9a3cd8cd317d9d5bebb3368c74507801e82dac33 Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Thu, 26 Sep 2024 16:45:47 +0000 Subject: [PATCH 170/170] feat: add CI to auto-label PRs (#17062) Add command `lake exe autolabel 17062` which uses `git diff` to find changes compared to `master`, searches for applicable GitHub topic labels (based on a defined mapping), and adds them to the PR using `gh`. Add GitHub workflow calling the script on creation of a new PR, automatically adding topic labels to the PR if applicable. Co-authored-by: adomani Co-authored-by: damiano Co-authored-by: Damiano Testa --- .github/workflows/add_label_from_diff.yaml | 42 +++ lakefile.lean | 10 + scripts/autolabel.lean | 310 +++++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 .github/workflows/add_label_from_diff.yaml create mode 100644 scripts/autolabel.lean diff --git a/.github/workflows/add_label_from_diff.yaml b/.github/workflows/add_label_from_diff.yaml new file mode 100644 index 0000000000000..271ac1b95ce59 --- /dev/null +++ b/.github/workflows/add_label_from_diff.yaml @@ -0,0 +1,42 @@ +name: Autolabel PRs + +on: + pull_request: + types: [opened] + push: + paths: + - scripts/autolabel.lean + - .github/workflows/add_label_from_diff.yaml + +jobs: + add_topic_label: + name: Add topic label + runs-on: ubuntu-latest + # Don't run on forks, where we wouldn't have permissions to add the label anyway. + if: github.repository == 'leanprover-community/mathlib4' + permissions: + issues: write + checks: write + pull-requests: write + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: install elan + run: | + set -o pipefail + curl -sSfL https://github.com/leanprover/elan/releases/download/v3.1.1/elan-x86_64-unknown-linux-gnu.tar.gz | tar xz + ./elan-init -y --default-toolchain none + echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" + - name: lake exe autolabel + run: | + # the checkout dance, to avoid a detached head + git checkout master + git checkout - + lake exe autolabel "$NUMBER" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.number }} diff --git a/lakefile.lean b/lakefile.lean index 601346ee071d0..87bbbfd1f21f0 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -84,6 +84,16 @@ lean_lib docs where ## Executables provided by Mathlib -/ +/-- +`lake exe autolabel 150100` adds a topic label to PR `150100` if there is a unique choice. +This requires GitHub CLI `gh` to be installed! + +Calling `lake exe autolabel` without a PR number will print the result without applying +any labels online. +-/ +lean_exe autolabel where + srcDir := "scripts" + /-- `lake exe cache get` retrieves precompiled `.olean` files from a central server. -/ lean_exe cache where root := `Cache.Main diff --git a/scripts/autolabel.lean b/scripts/autolabel.lean new file mode 100644 index 0000000000000..ccf7d7321c35e --- /dev/null +++ b/scripts/autolabel.lean @@ -0,0 +1,310 @@ +/- +Copyright (c) 2024 Damiano Testa. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jon Eugster, Damiano Testa +-/ +import Lean.Elab.Command + +/-! +# Automatic labelling of PRs + +This file contains the script to automatically assign a GitHub label to a PR. + +## Label definition + +The mapping from GitHub labels to Mathlib folders is done in this file and +needs to be updated here if necessary: + +* `AutoLabel.mathlibLabels` contains an assignment of GitHub labels to folders inside + the mathlib repository. If no folder is specified, a label like `t-set-theory` will be + interpreted as matching the folder `"Mathlib" / "SetTheory"`. +* `AutoLabel.mathlibUnlabelled` contains subfolders of `Mathlib/` which are deliberately + left without topic label. + +## lake exe autolabel + +`lake exe autolabel` uses `git diff --name-only origin/master...HEAD` to determine which +files have been modifed and then finds all labels which should be added based on these changes. +These are printed for testing purposes. + +`lake exe autolabel [NUMBER]` will further try to add the applicable labels +to the PR specified. This requires the **GitHub CLI** `gh` to be installed! +Example: `lake exe autolabel 10402` for PR #10402. + +For the time being, the script only adds a label if it finds a **single unique label** +which would apply. If multiple labels are found, nothing happens. + +## Workflow + +There is a mathlib workflow `.github/workflows/add_label_from_diff.yaml` which executes +this script automatically. + +Currently it is set to run only one time when a PR is created. + +## Tests + +Additionally, the script does a few consistency checks: + +- it ensures all paths in specified in `AutoLabel.mathlibLabels` exist +- It makes sure all subfolders of `Mathlib/` belong to at least one label. + There is `AutoLabel.mathlibUnlabelled` to add exceptions for this test. + +-/ + +open Lean System + +namespace AutoLabel + +/-- +A `Label` consists of the +* The `label` field is the actual GitHub label name. +* The `dirs` field is the array of all "root paths" such that a modification in a file contained + in one of these paths should be labelled with `label`. +* The `exclusions` field is the array of all "root paths" that are excluded, among the + ones that start with the ones in `dirs`. + Any modifications to a file in an excluded path is ignored for the purposes of labelling. +-/ +structure Label where + /-- The label name as it appears on GitHub -/ + label : String + /-- Array of paths which fall under this label. e.g. `"Mathlib" / "Algebra"`. + + For a label of the form `t-set-theory` this defaults to `#["Mathlib" / "SetTheory"]`. -/ + dirs : Array FilePath := if label.startsWith "t-" then + #["Mathlib" / ("".intercalate (label.splitOn "-" |>.drop 1 |>.map .capitalize))] + else #[] + /-- Array of paths which should be excluded. + Any modifications to a file in an excluded path are ignored for the purposes of labelling. -/ + exclusions : Array FilePath := #[] + deriving BEq, Hashable + +/-- +Mathlib labels and their corresponding folders. Add new labels and folders here! +-/ +def mathlibLabels : Array Label := #[ + { label := "t-algebra", + dirs := #[ + "Mathlib" / "Algebra", + "Mathlib" / "FieldTheory", + "Mathlib" / "RingTheory", + "Mathlib" / "GroupTheory", + "Mathlib" / "RepresentationTheory", + "Mathlib" / "LinearAlgebra"] }, + { label := "t-algebraic-geometry", + dirs := #[ + "Mathlib" / "AlgebraicGeometry", + "Mathlib" / "Geometry" / "RingedSpace"] }, + { label := "t-analysis" }, + { label := "t-category-theory" }, + { label := "t-combinatorics" }, + { label := "t-computability" }, + { label := "t-condensed" }, + { label := "t-data" }, + { label := "t-differential-geometry", + dirs := #["Mathlib" / "Geometry" / "Manifold"] }, + { label := "t-dynamics" }, + { label := "t-euclidean-geometry", + dirs := #["Mathlib" / "Geometry" / "Euclidean"] }, + { label := "t-linter", + dirs := #["Mathlib" / "Tactic" / "Linter"] }, + { label := "t-logic", + dirs := #[ + "Mathlib" / "Logic", + "Mathlib" / "ModelTheory"] }, + { label := "t-measure-probability", + dirs := #[ + "Mathlib" / "MeasureTheory", + "Mathlib" / "Probability", + "Mathlib" / "InformationTheory"] }, + { label := "t-meta", + dirs := #[ + "Mathlib" / "Control", + "Mathlib" / "Lean", + "Mathlib" / "Mathport", + "Mathlib" / "Tactic", + "Mathlib" / "Util"], + exclusions := #["Mathlib" / "Tactic" / "Linter"] }, + { label := "t-number-theory" }, + { label := "t-order" }, + { label := "t-set-theory" }, + { label := "t-topology", + dirs := #[ + "Mathlib" / "Topology", + "Mathlib" / "AlgebraicTopology"] }, + { label := "CI", + dirs := #[".github"] }, + { label := "IMO", + dirs := #["Archive" / "Imo"] } ] + +/-- Exceptions inside `Mathlib/` which are not covered by any label. -/ +def mathlibUnlabelled : Array FilePath := #[ + "Mathlib" / "Deprecated", + "Mathlib" / "Init", + "Mathlib" / "Testing", + "Mathlib" / "Std" ] + +/-- Checks if the folder `path` lies inside the folder `dir`. -/ +def _root_.System.FilePath.isPrefixOf (dir path : FilePath) : Bool := + -- use `dir / ""` to prevent partial matching of folder names + (dir / "").normalize.toString.isPrefixOf (path / "").normalize.toString + +/-- +Return all names of labels in `mathlibLabels` which match +at least one of the `files`. + +* `files`: array of relative paths starting from the mathlib root directory. +-/ +def getMatchingLabels (files : Array FilePath) : Array String := + let applicable := mathlibLabels.filter fun label ↦ + -- first exclude all files the label excludes, + -- then see if any file remains included by the label + let notExcludedFiles := files.filter fun file ↦ + label.exclusions.all (!·.isPrefixOf file) + label.dirs.any (fun dir ↦ notExcludedFiles.any (dir.isPrefixOf ·)) + -- return sorted list of label names + applicable.map (·.label) |>.qsort (· < ·) + +/-! +Testing the functionality of the declarations defined in this script +-/ +section Tests + +-- Test `FilePath.isPrefixOf` +#guard ("Mathlib" / "Algebra" : FilePath).isPrefixOf ("Mathlib" / "Algebra" / "Basic.lean") + +-- Test `FilePath.isPrefixOf` does not trigger on partial prefixes +#guard ! ("Mathlib" / "Algebra" : FilePath).isPrefixOf ("Mathlib" / "AlgebraicGeometry") + +#guard getMatchingLabels #[] == #[] +-- Test default value for `label.dirs` works +#guard getMatchingLabels #["Mathlib" / "SetTheory" / "ZFC"] == #["t-set-theory"] +-- Test exclusion +#guard getMatchingLabels #["Mathlib" / "Tactic"/ "Abel.lean"] == #["t-meta"] +#guard getMatchingLabels #["Mathlib" / "Tactic"/ "Linter" / "Lint.lean"] == #["t-linter"] +#guard getMatchingLabels #[ + "Mathlib" / "Tactic"/ "Linter" / "Lint.lean", + "Mathlib" / "Tactic" / "Abel.lean" ] == #["t-linter", "t-meta"] + +/-- Testing function to ensure the labels defined in `mathlibLabels` cover all +subfolders of `Mathlib/`. -/ +partial def findUncoveredPaths (path : FilePath) (exceptions : Array FilePath := #[]) : + IO <| Array FilePath := do + let mut notMatched : Array FilePath := #[] + -- all directories inside `path` + let subDirs ← (← path.readDir).map (·.path) |>.filterM (do FilePath.isDir ·) + for dir in subDirs do + -- if the sub directory is not matched by a label, + -- we go recursively into it + if (getMatchingLabels #[dir]).size == 0 then + notMatched := notMatched ++ (← findUncoveredPaths dir exceptions) + -- a directory should be flagged if none of its sub-directories is matched by a label + -- note: we assume here the base directory, i.e. "Mathlib" is never matched by a label, + -- therefore we skip this test. + if notMatched.size == subDirs.size then + if exceptions.contains path then + return #[] + else + return #[path] + else + return notMatched + +end Tests + +/-- +Create a message which GitHub CI parses as annotation and displays at the specified file. + +Note: `file` is duplicated below so that it is also visible in the plain text output. + +* `type`: "error" or "warning" +* `file`: file where the annotation should be displayed +* `title`: title of the annotation +* `message`: annotation message +-/ +def githubAnnotation (type file title message : String) : String := + s!"::{type} file={file},title={title}::{file}: {message}" + +end AutoLabel + +open IO AutoLabel in + +/-- `args` is expected to have length 0 or 1, where the first argument is the PR number. + +If a PR number is provided, the script requires GitHub CLI `gh` to be installed in order +to add the label to the PR. + +## Exit codes: + +- `0`: success +- `1`: invalid arguments provided +- `2`: invalid labels defined +- `3`: ~labels do not cover all of `Mathlib/`~ (unused; only emitting warning) +-/ +unsafe def main (args : List String): IO Unit := do + if args.length > 1 then + println s!"::error:: autolabel: invalid number of arguments ({args.length}), \ + expected at most 1. Please run without arguments or provide the target PR's \ + number as a single argument!" + IO.Process.exit 1 + let prNumber? := args[0]? + + -- test: validate that all paths in `mathlibLabels` actually exist + let mut valid := true + for label in mathlibLabels do + for dir in label.dirs do + unless ← FilePath.pathExists dir do + -- print github annotation error + println <| AutoLabel.githubAnnotation "error" "scripts/autolabel.lean" + s!"Misformatted `{ ``AutoLabel.mathlibLabels }`" + s!"directory '{dir}' does not exist but is included by label '{label.label}'. \ + Please update `{ ``AutoLabel.mathlibLabels }`!" + valid := false + for dir in label.exclusions do + unless ← FilePath.pathExists dir do + -- print github annotation error + println <| AutoLabel.githubAnnotation "error" "scripts/autolabel.lean" + s!"Misformatted `{ ``AutoLabel.mathlibLabels }`" + s!"directory '{dir}' does not exist but is excluded by label '{label.label}'. \ + Please update `{ ``AutoLabel.mathlibLabels }`!" + valid := false + unless valid do + IO.Process.exit 2 + + -- test: validate that the labels cover all of the `Mathlib/` folder + let notMatchedPaths ← findUncoveredPaths "Mathlib" (exceptions := mathlibUnlabelled) + if notMatchedPaths.size > 0 then + -- print github annotation warning + -- note: only emitting a warning because the workflow is only triggered on the first commit + -- of a PR and could therefore lead to unexpected behaviour if a folder was created later. + println <| AutoLabel.githubAnnotation "warning" "scripts/autolabel.lean" + s!"Incomplete `{ ``AutoLabel.mathlibLabels }`" + s!"the following paths inside `Mathlib/` are not covered \ + by any label: {notMatchedPaths} Please modify `AutoLabel.mathlibLabels` accordingly!" + -- IO.Process.exit 3 + + -- get the modified files + let gitDiff ← IO.Process.run { + cmd := "git", + args := #["diff", "--name-only", "origin/master...HEAD"] } + let modifiedFiles : Array FilePath := (gitDiff.splitOn "\n").toArray.map (⟨·⟩) + + -- find labels covering the modified files + let labels := getMatchingLabels modifiedFiles + + match labels with + | #[] => + println s!"No applicable labels found!" + | #[label] => + println s!"Exactly one label found: {label}" + match prNumber? with + | some n => + let _ ← IO.Process.run { + cmd := "gh", + args := #["pr", "edit", n, "--add-label", label] } + println s!"Added label: {label}" + | none => + println s!"No PR-number provided, skipping adding labels. \ + (call `lake exe autolabel 150602` to add the labels to PR `150602`)" + | labels => + println s!"Multiple labels found: {labels}" + println s!"Not adding any label." + IO.Process.exit 0